diff --git a/configure.ac b/configure.ac
index a48b734..d2f86b8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
# Versioning.
m4_define([dc_version_major],[0])
-m4_define([dc_version_minor],[6])
+m4_define([dc_version_minor],[7])
m4_define([dc_version_micro],[0])
m4_define([dc_version_suffix],[devel-Subsurface-branch])
m4_define([dc_version],dc_version_major.dc_version_minor.dc_version_micro[]m4_ifset([dc_version_suffix],-[dc_version_suffix]))
diff --git a/doc/man/dc_parser_get_field.3 b/doc/man/dc_parser_get_field.3
index 7d9e54e..2b276a1 100644
--- a/doc/man/dc_parser_get_field.3
+++ b/doc/man/dc_parser_get_field.3
@@ -172,8 +172,10 @@ for gauge (i.e., running as a record and not computing, say,
decompression events),
.Dv DC_DIVEMODE_OC
for standard open-circuit diving, and
-.Dv DC_DIVEMODE_CC
-for closed-circuit
+.Dv DC_DIVEMODE_CCR
+and
+.Dv DC_DIVEMODE_SCR
+for respectively closed circuit and semi closed circuit
.Dq rebreather
diving.
.El
diff --git a/examples/output_xml.c b/examples/output_xml.c
index 5153fc8..1e9c569 100644
--- a/examples/output_xml.c
+++ b/examples/output_xml.c
@@ -367,7 +367,7 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u
}
if (status != DC_STATUS_UNSUPPORTED) {
- const char *names[] = {"freedive", "gauge", "oc", "cc"};
+ const char *names[] = {"freedive", "gauge", "oc", "ccr", "scr"};
fprintf (output->ostream, "%s\n",
names[divemode]);
}
diff --git a/include/libdivecomputer/Makefile.am b/include/libdivecomputer/Makefile.am
index e666f61..00926d0 100644
--- a/include/libdivecomputer/Makefile.am
+++ b/include/libdivecomputer/Makefile.am
@@ -7,6 +7,7 @@ libdivecomputer_HEADERS = \
buffer.h \
descriptor.h \
iterator.h \
+ iostream.h \
device.h \
parser.h \
datetime.h \
diff --git a/include/libdivecomputer/custom_io.h b/include/libdivecomputer/custom_io.h
index 14a66ca..1e310b9 100644
--- a/include/libdivecomputer/custom_io.h
+++ b/include/libdivecomputer/custom_io.h
@@ -1,67 +1,14 @@
#ifndef CUSTOM_IO_H
#define CUSTOM_IO_H
+#include
+
#include "common.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-// Verbatim copy from src/serial.h
-
-#ifndef __SERIAL_TYPES__
-#define __SERIAL_TYPES__
-// Don't re-declare when we're internal
-/**
- * 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;
-
-/**
- * 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;
-
-/**
- * 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;
-
-/**
- * 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;
-
-/**
- * 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;
-
-#endif /* __SERIAL_TYPES__ */
-
struct dc_context_t;
struct dc_user_device_t;
diff --git a/include/libdivecomputer/iostream.h b/include/libdivecomputer/iostream.h
new file mode 100644
index 0000000..dab5daf
--- /dev/null
+++ b/include/libdivecomputer/iostream.h
@@ -0,0 +1,290 @@
+/*
+ * libdivecomputer
+ *
+ * Copyright (C) 2016 Jef Driesen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#ifndef DC_IOSTREAM_H
+#define DC_IOSTREAM_H
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * Opaque object representing a I/O stream.
+ */
+typedef struct dc_iostream_t dc_iostream_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;
+
+/**
+ * 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;
+
+/**
+ * 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;
+
+/**
+ * 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;
+
+/**
+ * The 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;
+
+/**
+ * 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] iostream A valid I/O stream.
+ * @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_iostream_set_timeout (dc_iostream_t *iostream, int timeout);
+
+/**
+ * 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] iostream A valid I/O stream.
+ * @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_iostream_set_latency (dc_iostream_t *iostream, unsigned int value);
+
+/**
+ * Set the state of the half duplex emulation.
+ *
+ * @param[in] iostream A valid I/O stream.
+ * @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_iostream_set_halfduplex (dc_iostream_t *iostream, unsigned int value);
+
+/**
+ * Set the state of the break condition.
+ *
+ * @param[in] iostream A valid I/O stream.
+ * @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_iostream_set_break (dc_iostream_t *iostream, unsigned int value);
+
+/**
+ * Set the state of the DTR line.
+ *
+ * @param[in] iostream A valid I/O stream.
+ * @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_iostream_set_dtr (dc_iostream_t *iostream, unsigned int value);
+
+/**
+ * Set the state of the RTS line.
+ *
+ * @param[in] iostream A valid I/O stream.
+ * @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_iostream_set_rts (dc_iostream_t *iostream, unsigned int value);
+
+/**
+ * Query the state of the line signals.
+ *
+ * @param[in] iostream A valid I/O stream.
+ * @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_iostream_get_lines (dc_iostream_t *iostream, unsigned int *value);
+
+/**
+ * Query the number of available bytes in the input buffer.
+ *
+ * @param[in] iostream A valid I/O stream.
+ * @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_iostream_get_available (dc_iostream_t *iostream, size_t *value);
+
+/**
+ * Configure the line settings.
+ *
+ * @param[in] iostream A valid I/O stream.
+ * @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_iostream_configure (dc_iostream_t *iostream, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
+
+/**
+ * Read data from the I/O stream.
+ *
+ * @param[in] iostream A valid I/O stream.
+ * @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_iostream_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
+
+/**
+ * Write data to the I/O stream.
+ *
+ * @param[in] iostream A valid I/O stream.
+ * @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_iostream_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
+
+/**
+ * Flush the internal output buffer and wait until the data has been
+ * transmitted.
+ *
+ * @param[in] iostream A valid I/O stream.
+ * @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
+ * on failure.
+ */
+dc_status_t
+dc_iostream_flush (dc_iostream_t *iostream);
+
+/**
+ * Discards all data from the internal buffers.
+ *
+ * @param[in] iostream A valid I/O stream.
+ * @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_iostream_purge (dc_iostream_t *iostream, dc_direction_t direction);
+
+/**
+ * Suspend execution of the current thread for the specified amount of
+ * time.
+ *
+ * @param[in] iostream A valid I/O stream.
+ * @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_iostream_sleep (dc_iostream_t *iostream, unsigned int milliseconds);
+
+/**
+ * Close the I/O stream and free all resources.
+ *
+ * @param[in] iostream A valid I/O stream.
+ * @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
+ * on failure.
+ */
+dc_status_t
+dc_iostream_close (dc_iostream_t *iostream);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* DC_IOSTREAM_H */
diff --git a/include/libdivecomputer/parser.h b/include/libdivecomputer/parser.h
index 305a136..db38da8 100644
--- a/include/libdivecomputer/parser.h
+++ b/include/libdivecomputer/parser.h
@@ -132,9 +132,13 @@ typedef enum dc_divemode_t {
DC_DIVEMODE_FREEDIVE,
DC_DIVEMODE_GAUGE,
DC_DIVEMODE_OC, /* Open circuit */
- DC_DIVEMODE_CC /* Closed circuit */
+ DC_DIVEMODE_CCR, /* Closed circuit rebreather */
+ DC_DIVEMODE_SCR /* Semi-closed circuit rebreather */
} dc_divemode_t;
+/* For backwards compatibility */
+#define DC_DIVEMODE_CC DC_DIVEMODE_CCR
+
typedef enum dc_deco_type_t {
DC_DECO_NDL,
DC_DECO_SAFETYSTOP,
diff --git a/msvc/libdivecomputer.vcproj b/msvc/libdivecomputer.vcproj
index 242276a..c54c3d7 100644
--- a/msvc/libdivecomputer.vcproj
+++ b/msvc/libdivecomputer.vcproj
@@ -246,6 +246,10 @@
RelativePath="..\src\cressi_leonardo_parser.c"
>
+
+
@@ -294,6 +298,10 @@
RelativePath="..\src\ihex.c"
>
+
+
@@ -418,6 +426,10 @@
RelativePath="..\src\shearwater_predator_parser.c"
>
+
+
@@ -572,6 +584,10 @@
RelativePath="..\src\cressi_leonardo.h"
>
+
+
@@ -624,6 +640,14 @@
RelativePath="..\src\ihex.h"
>
+
+
+
+
@@ -748,6 +772,10 @@
RelativePath="..\src\shearwater_predator.h"
>
+
+
diff --git a/src/Makefile.am b/src/Makefile.am
index 1545bc7..49ae4e7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,6 +17,7 @@ endif
libdivecomputer_la_SOURCES = \
version.c \
descriptor.c \
+ iostream-private.h iostream.c \
iterator-private.h iterator.c \
common-private.h common.c \
context-private.h context.c \
@@ -77,9 +78,12 @@ else
libdivecomputer_la_SOURCES += serial.h serial_posix.c
endif
+libdivecomputer_la_SOURCES += socket.h socket.c
libdivecomputer_la_SOURCES += irda.h irda.c
libdivecomputer_la_SOURCES += usbhid.h usbhid.c
libdivecomputer_la_SOURCES += bluetooth.h bluetooth.c
+libdivecomputer_la_SOURCES += custom.h custom.c
+libdivecomputer_la_SOURCES += custom_io.c
if OS_WIN32
libdivecomputer_la_SOURCES += libdivecomputer.rc
@@ -97,7 +101,7 @@ libdivecomputer.lo: revision.h
FORCE:
$(top_srcdir)/revision: FORCE
- @if (test -d $(top_srcdir)/.git && cd $(top_srcdir) \
+ @if (test -e $(top_srcdir)/.git && cd $(top_srcdir) \
&& git rev-parse --verify HEAD) > revision-t 2>/dev/null \
&& ! cmp -s revision-t $@; then \
mv -f revision-t $@; \
diff --git a/src/atomics_cobalt_parser.c b/src/atomics_cobalt_parser.c
index a55e672..7d30ca3 100644
--- a/src/atomics_cobalt_parser.c
+++ b/src/atomics_cobalt_parser.c
@@ -214,7 +214,7 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
*((dc_divemode_t *) value) = DC_DIVEMODE_OC;
break;
case 1: // Closed Circuit
- *((dc_divemode_t *) value) = DC_DIVEMODE_CC;
+ *((dc_divemode_t *) value) = DC_DIVEMODE_CCR;
break;
default:
return DC_STATUS_DATAFORMAT;
diff --git a/src/bluetooth.c b/src/bluetooth.c
index 01a3e96..b139892 100644
--- a/src/bluetooth.c
+++ b/src/bluetooth.c
@@ -25,22 +25,14 @@
#include // malloc, free
+#include "socket.h"
+
#ifdef _WIN32
-#define NOGDI
-#include
-#include
#ifdef HAVE_WS2BTH_H
#define BLUETOOTH
#include
#endif
#else
-#include // errno
-#include // close
-#include // socket, getsockopt
-#include // socket, getsockopt
-#include // select
-#include // ioctl
-#include
#ifdef HAVE_BLUEZ
#define BLUETOOTH
#include
@@ -51,36 +43,10 @@
#endif
#include "bluetooth.h"
+
#include "common-private.h"
#include "context-private.h"
-
-#ifdef _WIN32
-typedef int s_ssize_t;
-typedef DWORD s_errcode_t;
-#define S_ERRNO WSAGetLastError ()
-#define S_EINTR WSAEINTR
-#define S_EAGAIN WSAEWOULDBLOCK
-#define S_ENOMEM WSA_NOT_ENOUGH_MEMORY
-#define S_EINVAL WSAEINVAL
-#define S_EACCES WSAEACCES
-#define S_EAFNOSUPPORT WSAEAFNOSUPPORT
-#define S_INVALID INVALID_SOCKET
-#define S_IOCTL ioctlsocket
-#define S_CLOSE closesocket
-#else
-typedef ssize_t s_ssize_t;
-typedef int s_errcode_t;
-#define S_ERRNO errno
-#define S_EINTR EINTR
-#define S_EAGAIN EAGAIN
-#define S_ENOMEM ENOMEM
-#define S_EINVAL EINVAL
-#define S_EACCES EACCES
-#define S_EAFNOSUPPORT EAFNOSUPPORT
-#define S_INVALID -1
-#define S_IOCTL ioctl
-#define S_CLOSE close
-#endif
+#include "iostream-private.h"
#ifdef _WIN32
#define DC_ADDRESS_FORMAT "%012I64X"
@@ -93,34 +59,27 @@ typedef int s_errcode_t;
#define MAX_DEVICES 255
#define MAX_PERIODS 8
-struct dc_bluetooth_t {
- dc_context_t *context;
-#ifdef _WIN32
- SOCKET fd;
-#else
- int fd;
-#endif
- int timeout;
-};
+#define ISINSTANCE(device) dc_iostream_isinstance((device), &dc_bluetooth_vtable)
#ifdef BLUETOOTH
-static dc_status_t
-syserror(s_errcode_t errcode)
-{
- switch (errcode) {
- case S_EINVAL:
- return DC_STATUS_INVALIDARGS;
- case S_ENOMEM:
- return DC_STATUS_NOMEMORY;
- case S_EACCES:
- return DC_STATUS_NOACCESS;
- case S_EAFNOSUPPORT:
- return DC_STATUS_UNSUPPORTED;
- default:
- return DC_STATUS_IO;
- }
-}
-#endif
+static const dc_iostream_vtable_t dc_bluetooth_vtable = {
+ sizeof(dc_socket_t),
+ dc_socket_set_timeout, /* set_timeout */
+ dc_socket_set_latency, /* set_latency */
+ dc_socket_set_halfduplex, /* set_halfduplex */
+ dc_socket_set_break, /* set_break */
+ dc_socket_set_dtr, /* set_dtr */
+ dc_socket_set_rts, /* set_rts */
+ dc_socket_get_lines, /* get_lines */
+ dc_socket_get_available, /* get_received */
+ dc_socket_configure, /* configure */
+ dc_socket_read, /* read */
+ dc_socket_write, /* write */
+ dc_socket_flush, /* flush */
+ dc_socket_purge, /* purge */
+ dc_socket_sleep, /* sleep */
+ dc_socket_close, /* close */
+};
#ifdef HAVE_BLUEZ
static dc_bluetooth_address_t
@@ -147,75 +106,41 @@ dc_address_set (bdaddr_t *ba, dc_bluetooth_address_t address)
}
}
#endif
+#endif
dc_status_t
-dc_bluetooth_open (dc_bluetooth_t **out, dc_context_t *context)
+dc_bluetooth_open (dc_iostream_t **out, dc_context_t *context)
{
#ifdef BLUETOOTH
dc_status_t status = DC_STATUS_SUCCESS;
- dc_bluetooth_t *device = NULL;
+ dc_socket_t *device = NULL;
if (out == NULL)
return DC_STATUS_INVALIDARGS;
// Allocate memory.
- device = (dc_bluetooth_t *) malloc (sizeof (dc_bluetooth_t));
+ device = (dc_socket_t *) dc_iostream_allocate (context, &dc_bluetooth_vtable);
if (device == NULL) {
SYSERROR (context, S_ENOMEM);
return DC_STATUS_NOMEMORY;
}
- // Library context.
- device->context = context;
-
- // Default to blocking reads.
- device->timeout = -1;
-
+ // Open the socket.
#ifdef _WIN32
- // Initialize the winsock dll.
- WSADATA wsaData;
- WORD wVersionRequested = MAKEWORD (2, 2);
- int rc = WSAStartup (wVersionRequested, &wsaData);
- if (rc != 0) {
- SYSERROR (context, rc);
- status = DC_STATUS_UNSUPPORTED;
+ status = dc_socket_open (&device->base, AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
+#else
+ status = dc_socket_open (&device->base, AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+#endif
+ if (status != DC_STATUS_SUCCESS) {
goto error_free;
}
- // Confirm that the winsock dll supports version 2.2.
- // Note that if the dll supports versions greater than 2.2 in addition to
- // 2.2, it will still return 2.2 since that is the version we requested.
- if (LOBYTE (wsaData.wVersion) != 2 ||
- HIBYTE (wsaData.wVersion) != 2) {
- ERROR (context, "Incorrect winsock version.");
- status = DC_STATUS_UNSUPPORTED;
- goto error_wsacleanup;
- }
-#endif
-
- // Open the socket.
-#ifdef _WIN32
- device->fd = socket (AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
-#else
- device->fd = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
-#endif
- if (device->fd == S_INVALID) {
- s_errcode_t errcode = S_ERRNO;
- SYSERROR (context, errcode);
- status = syserror(errcode);
- goto error_wsacleanup;
- }
-
- *out = device;
+ *out = (dc_iostream_t *) device;
return DC_STATUS_SUCCESS;
-error_wsacleanup:
-#ifdef _WIN32
- WSACleanup ();
error_free:
-#endif
- free (device);
+ dc_iostream_deallocate ((dc_iostream_t *) device);
return status;
#else
return DC_STATUS_UNSUPPORTED;
@@ -223,66 +148,12 @@ error_free:
}
dc_status_t
-dc_bluetooth_close (dc_bluetooth_t *device)
+dc_bluetooth_discover (dc_iostream_t *abstract, dc_bluetooth_callback_t callback, void *userdata)
{
#ifdef BLUETOOTH
dc_status_t status = DC_STATUS_SUCCESS;
- if (device == NULL)
- return DC_STATUS_SUCCESS;
-
- // Terminate all send and receive operations.
- shutdown (device->fd, 0);
-
- // Close the socket.
- if (S_CLOSE (device->fd) != 0) {
- s_errcode_t errcode = S_ERRNO;
- SYSERROR (device->context, errcode);
- dc_status_set_error(&status, syserror(errcode));
- }
-
-#ifdef _WIN32
- // Terminate the winsock dll.
- if (WSACleanup () != 0) {
- s_errcode_t errcode = S_ERRNO;
- SYSERROR (device->context, errcode);
- dc_status_set_error(&status, syserror(errcode));
- }
-#endif
-
- // Free memory.
- free (device);
-
- return status;
-#else
- return DC_STATUS_UNSUPPORTED;
-#endif
-}
-
-dc_status_t
-dc_bluetooth_set_timeout (dc_bluetooth_t *device, int timeout)
-{
-#ifdef BLUETOOTH
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "Timeout: value=%i", timeout);
-
- device->timeout = timeout;
-
- return DC_STATUS_SUCCESS;
-#else
- return DC_STATUS_UNSUPPORTED;
-#endif
-}
-
-dc_status_t
-dc_bluetooth_discover (dc_bluetooth_t *device, dc_bluetooth_callback_t callback, void *userdata)
-{
-#ifdef BLUETOOTH
- dc_status_t status = DC_STATUS_SUCCESS;
-
- if (device == NULL)
+ if (!ISINSTANCE (abstract))
return DC_STATUS_INVALIDARGS;
#ifdef _WIN32
@@ -299,8 +170,8 @@ dc_bluetooth_discover (dc_bluetooth_t *device, dc_bluetooth_callback_t callback,
// No remote bluetooth devices found.
status = DC_STATUS_SUCCESS;
} else {
- SYSERROR (device->context, errcode);
- status = syserror(errcode);
+ SYSERROR (abstract->context, errcode);
+ status = dc_socket_syserror(errcode);
}
goto error_exit;
}
@@ -319,15 +190,15 @@ dc_bluetooth_discover (dc_bluetooth_t *device, dc_bluetooth_callback_t callback,
if (errcode == WSA_E_NO_MORE || errcode == WSAENOMORE) {
break; // No more results.
}
- SYSERROR (device->context, errcode);
- status = syserror(errcode);
+ SYSERROR (abstract->context, errcode);
+ status = dc_socket_syserror(errcode);
goto error_close;
}
if (pwsaResults->dwNumberOfCsAddrs == 0 ||
pwsaResults->lpcsaBuffer == NULL ||
pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr == NULL) {
- ERROR (device->context, "Invalid results returned");
+ ERROR (abstract->context, "Invalid results returned");
status = DC_STATUS_IO;
goto error_close;
}
@@ -336,7 +207,7 @@ dc_bluetooth_discover (dc_bluetooth_t *device, dc_bluetooth_callback_t callback,
dc_bluetooth_address_t address = sa->btAddr;
const char *name = (char *) pwsaResults->lpszServiceInstanceName;
- INFO (device->context, "Discover: address=" DC_ADDRESS_FORMAT ", name=%s", address, name);
+ INFO (abstract->context, "Discover: address=" DC_ADDRESS_FORMAT ", name=%s", address, name);
if (callback) callback (address, name, userdata);
@@ -349,8 +220,8 @@ error_close:
int dev = hci_get_route (NULL);
if (dev < 0) {
s_errcode_t errcode = S_ERRNO;
- SYSERROR (device->context, errcode);
- status = syserror(errcode);
+ SYSERROR (abstract->context, errcode);
+ status = dc_socket_syserror(errcode);
goto error_exit;
}
@@ -358,8 +229,8 @@ error_close:
int fd = hci_open_dev (dev);
if (fd < 0) {
s_errcode_t errcode = S_ERRNO;
- SYSERROR (device->context, errcode);
- status = syserror(errcode);
+ SYSERROR (abstract->context, errcode);
+ status = dc_socket_syserror(errcode);
goto error_exit;
}
@@ -367,8 +238,8 @@ error_close:
inquiry_info *devices = (inquiry_info *) malloc (MAX_DEVICES * sizeof(inquiry_info));
if (devices == NULL) {
s_errcode_t errcode = S_ERRNO;
- SYSERROR (device->context, errcode);
- status = syserror(errcode);
+ SYSERROR (abstract->context, errcode);
+ status = dc_socket_syserror(errcode);
goto error_close;
}
@@ -378,8 +249,8 @@ error_close:
int ndevices = hci_inquiry (dev, MAX_PERIODS, MAX_DEVICES, NULL, &devices, IREQ_CACHE_FLUSH);
if (ndevices < 0) {
s_errcode_t errcode = S_ERRNO;
- SYSERROR (device->context, errcode);
- status = syserror(errcode);
+ SYSERROR (abstract->context, errcode);
+ status = dc_socket_syserror(errcode);
goto error_free;
}
@@ -393,7 +264,7 @@ error_close:
name = NULL;
}
- INFO (device->context, "Discover: address=" DC_ADDRESS_FORMAT ", name=%s", address, name);
+ INFO (abstract->context, "Discover: address=" DC_ADDRESS_FORMAT ", name=%s", address, name);
if (callback) callback (address, name, userdata);
}
@@ -412,13 +283,15 @@ error_exit:
}
dc_status_t
-dc_bluetooth_connect (dc_bluetooth_t *device, dc_bluetooth_address_t address, unsigned int port)
+dc_bluetooth_connect (dc_iostream_t *abstract, dc_bluetooth_address_t address, unsigned int port)
{
#ifdef BLUETOOTH
- if (device == NULL)
+ dc_socket_t *device = (dc_socket_t *) abstract;
+
+ if (!ISINSTANCE (abstract))
return DC_STATUS_INVALIDARGS;
- INFO (device->context, "Connect: address=" DC_ADDRESS_FORMAT ", port=%d", address, port);
+ INFO (abstract->context, "Connect: address=" DC_ADDRESS_FORMAT ", port=%d", address, port);
#ifdef _WIN32
SOCKADDR_BTH sa;
@@ -433,171 +306,7 @@ dc_bluetooth_connect (dc_bluetooth_t *device, dc_bluetooth_address_t address, un
dc_address_set (&sa.rc_bdaddr, address);
#endif
- if (connect (device->fd, (struct sockaddr *) &sa, sizeof (sa)) != 0) {
- s_errcode_t errcode = S_ERRNO;
- SYSERROR (device->context, errcode);
- return syserror(errcode);
- }
-
- return DC_STATUS_SUCCESS;
-#else
- return DC_STATUS_UNSUPPORTED;
-#endif
-}
-
-dc_status_t
-dc_bluetooth_get_available (dc_bluetooth_t *device, size_t *value)
-{
-#ifdef BLUETOOTH
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
-#ifdef _WIN32
- unsigned long bytes = 0;
-#else
- int bytes = 0;
-#endif
-
- if (S_IOCTL (device->fd, FIONREAD, &bytes) != 0) {
- s_errcode_t errcode = S_ERRNO;
- SYSERROR (device->context, errcode);
- return syserror(errcode);
- }
-
- if (value)
- *value = bytes;
-
- return DC_STATUS_SUCCESS;
-#else
- return DC_STATUS_UNSUPPORTED;
-#endif
-}
-
-dc_status_t
-dc_bluetooth_read (dc_bluetooth_t *device, void *data, size_t size, size_t *actual)
-{
-#ifdef BLUETOOTH
- dc_status_t status = DC_STATUS_SUCCESS;
- size_t nbytes = 0;
-
- if (device == NULL) {
- status = DC_STATUS_INVALIDARGS;
- goto out_invalidargs;
- }
-
- while (nbytes < size) {
- fd_set fds;
- FD_ZERO (&fds);
- FD_SET (device->fd, &fds);
-
- struct timeval tvt;
- if (device->timeout > 0) {
- tvt.tv_sec = (device->timeout / 1000);
- tvt.tv_usec = (device->timeout % 1000) * 1000;
- } else if (device->timeout == 0) {
- timerclear (&tvt);
- }
-
- int rc = select (device->fd + 1, &fds, NULL, NULL, device->timeout >= 0 ? &tvt : NULL);
- if (rc < 0) {
- s_errcode_t errcode = S_ERRNO;
- if (errcode == S_EINTR)
- continue; // Retry.
- SYSERROR (device->context, errcode);
- status = syserror(errcode);
- goto out;
- } else if (rc == 0) {
- break; // Timeout.
- }
-
- s_ssize_t n = recv (device->fd, (char*) data + nbytes, size - nbytes, 0);
- if (n < 0) {
- s_errcode_t errcode = S_ERRNO;
- if (errcode == S_EINTR || errcode == S_EAGAIN)
- continue; // Retry.
- SYSERROR (device->context, errcode);
- status = syserror(errcode);
- goto out;
- } else if (n == 0) {
- break; // EOF reached.
- }
-
- nbytes += n;
- }
-
- if (nbytes != size) {
- status = DC_STATUS_TIMEOUT;
- }
-
-out:
- HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Read", (unsigned char *) data, nbytes);
-
-out_invalidargs:
- if (actual)
- *actual = nbytes;
-
- return status;
-#else
- return DC_STATUS_UNSUPPORTED;
-#endif
-}
-
-dc_status_t
-dc_bluetooth_write (dc_bluetooth_t *device, const void *data, size_t size, size_t *actual)
-{
-#ifdef BLUETOOTH
- dc_status_t status = DC_STATUS_SUCCESS;
- size_t nbytes = 0;
-
- if (device == NULL) {
- status = DC_STATUS_INVALIDARGS;
- goto out_invalidargs;
- }
-
- while (nbytes < size) {
- fd_set fds;
- FD_ZERO (&fds);
- FD_SET (device->fd, &fds);
-
- int rc = select (device->fd + 1, NULL, &fds, NULL, NULL);
- if (rc < 0) {
- s_errcode_t errcode = S_ERRNO;
- if (errcode == S_EINTR)
- continue; // Retry.
- SYSERROR (device->context, errcode);
- status = syserror(errcode);
- goto out;
- } else if (rc == 0) {
- break; // Timeout.
- }
-
- s_ssize_t n = send (device->fd, (const char *) data + nbytes, size - nbytes, 0);
- if (n < 0) {
- s_errcode_t errcode = S_ERRNO;
- if (errcode == S_EINTR || errcode == S_EAGAIN)
- continue; // Retry.
- SYSERROR (device->context, errcode);
- status = syserror(errcode);
- goto out;
- } else if (n == 0) {
- break; // EOF.
- }
-
- nbytes += n;
- }
-
- if (nbytes != size) {
- status = DC_STATUS_TIMEOUT;
- }
-
-out:
- HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Write", (const unsigned char *) data, nbytes);
-
-out_invalidargs:
- if (actual)
- *actual = nbytes;
-
- return status;
+ return dc_socket_connect (&device->base, (struct sockaddr *) &sa, sizeof (sa));
#else
return DC_STATUS_UNSUPPORTED;
#endif
diff --git a/src/bluetooth.h b/src/bluetooth.h
index d2e3868..1a8e947 100644
--- a/src/bluetooth.h
+++ b/src/bluetooth.h
@@ -24,16 +24,12 @@
#include
#include
+#include
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-/**
- * Opaque object representing a bluetooth connection.
- */
-typedef struct dc_bluetooth_t dc_bluetooth_t;
-
/**
* Bluetooth address (48 bits).
*/
@@ -55,118 +51,37 @@ typedef void (*dc_bluetooth_callback_t) (dc_bluetooth_address_t address, const c
/**
* Open an bluetooth connection.
*
- * @param[out] bluetooth A location to store the bluetooth connection.
+ * @param[out] iostream A location to store the bluetooth 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_bluetooth_open (dc_bluetooth_t **bluetooth, dc_context_t *context);
-
-/**
- * Close the bluetooth connection and free all resources.
- *
- * @param[in] bluetooth A valid bluetooth connection.
- * @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
- * on failure.
- */
-dc_status_t
-dc_bluetooth_close (dc_bluetooth_t *bluetooth);
-
-/**
- * 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] bluetooth A valid bluetooth 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_bluetooth_set_timeout (dc_bluetooth_t *bluetooth, int timeout);
+dc_bluetooth_open (dc_iostream_t **iostream, dc_context_t *context);
/**
* Enumerate the bluetooth devices.
*
- * @param[in] bluetooth A valid bluetooth connection.
+ * @param[in] iostream A valid bluetooth 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_bluetooth_discover (dc_bluetooth_t *bluetooth, dc_bluetooth_callback_t callback, void *userdata);
+dc_bluetooth_discover (dc_iostream_t *iostream, dc_bluetooth_callback_t callback, void *userdata);
/**
* Connect to an bluetooth device.
*
- * @param[in] bluetooth A valid bluetooth connection.
+ * @param[in] iostream A valid bluetooth connection.
* @param[in] address The bluetooth device address.
* @param[in] port The bluetooth port number.
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
* on failure.
*/
dc_status_t
-dc_bluetooth_connect (dc_bluetooth_t *bluetooth, dc_bluetooth_address_t address, unsigned int port);
-
-/**
- * Query the number of available bytes in the input buffer.
- *
- * @param[in] bluetooth A valid bluetooth 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_bluetooth_get_available (dc_bluetooth_t *bluetooth, size_t *value);
-
-/**
- * Read data from the bluetooth connection.
- *
- * @param[in] bluetooth A valid bluetooth 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_bluetooth_read (dc_bluetooth_t *bluetooth, void *data, size_t size, size_t *actual);
-
-/**
- * Write data to the bluetooth connection.
- *
- * @param[in] bluetooth A valid bluetooth 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_bluetooth_write (dc_bluetooth_t *bluetooth, const void *data, size_t size, size_t *actual);
+dc_bluetooth_connect (dc_iostream_t *iostream, dc_bluetooth_address_t address, unsigned int port);
#ifdef __cplusplus
}
diff --git a/src/citizen_aqualand.c b/src/citizen_aqualand.c
index 47ba87f..3af5d52 100644
--- a/src/citizen_aqualand.c
+++ b/src/citizen_aqualand.c
@@ -34,7 +34,7 @@
typedef struct citizen_aqualand_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned char fingerprint[8];
} citizen_aqualand_device_t;
@@ -73,40 +73,40 @@ citizen_aqualand_device_open (dc_device_t **out, dc_context_t *context, const ch
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
memset (device->fingerprint, 0, sizeof (device->fingerprint));
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (4800 8N1).
- status = dc_serial_configure (device->port, 4800, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 4800, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (1000ms).
- status = dc_serial_set_timeout (device->port, 1000);
+ status = dc_iostream_set_timeout (device->iostream, 1000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Make sure everything is in a sane state.
- dc_serial_sleep (device->port, 300);
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_sleep (device->iostream, 300);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
*out = (dc_device_t *) device;
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -121,7 +121,7 @@ citizen_aqualand_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -159,21 +159,21 @@ citizen_aqualand_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
return DC_STATUS_NOMEMORY;
}
- dc_serial_set_dtr (device->port, 1);
+ dc_iostream_set_dtr (device->iostream, 1);
// Send the init byte.
const unsigned char init[] = {0x7F};
- status = dc_serial_write (device->port, init, sizeof (init), NULL);
+ status = dc_iostream_write (device->iostream, init, sizeof (init), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
}
- dc_serial_sleep(device->port, 1200);
+ dc_iostream_sleep(device->iostream, 1200);
// Send the command.
const unsigned char command[] = {0xFF};
- status = dc_serial_write (device->port, command, sizeof (command), NULL);
+ status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -182,7 +182,7 @@ citizen_aqualand_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
while (1) {
// Receive the response packet.
unsigned char answer[32] = {0};
- status = dc_serial_read (device->port, answer, sizeof (answer), NULL);
+ status = dc_iostream_read (device->iostream, answer, sizeof (answer), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -191,7 +191,7 @@ citizen_aqualand_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
dc_buffer_append(buffer, answer, sizeof (answer));
// Send the command.
- status = dc_serial_write (device->port, command, sizeof (command), NULL);
+ status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -201,7 +201,7 @@ citizen_aqualand_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
break;
}
- dc_serial_set_dtr (device->port, 0);
+ dc_iostream_set_dtr (device->iostream, 0);
return DC_STATUS_SUCCESS;
}
diff --git a/src/cochran_commander.c b/src/cochran_commander.c
index 688c019..e21ec7e 100644
--- a/src/cochran_commander.c
+++ b/src/cochran_commander.c
@@ -94,7 +94,7 @@ typedef struct cochran_device_layout_t {
typedef struct cochran_commander_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
const cochran_device_layout_t *layout;
unsigned char id[67];
unsigned char fingerprint[6];
@@ -305,30 +305,30 @@ 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).
- status = dc_serial_configure (device->port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_TWO, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 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 status;
}
// Set the timeout for receiving data (5000 ms).
- status = dc_serial_set_timeout (device->port, 5000);
+ status = dc_iostream_set_timeout (device->iostream, 5000);
if (status != DC_STATUS_SUCCESS) {
ERROR (device->base.context, "Failed to set the timeout.");
return status;
}
// Wake up DC and trigger heartbeat
- dc_serial_set_break(device->port, 1);
- dc_serial_sleep(device->port, 16);
- dc_serial_set_break(device->port, 0);
+ dc_iostream_set_break(device->iostream, 1);
+ dc_iostream_sleep(device->iostream, 16);
+ dc_iostream_set_break(device->iostream, 0);
// Clear old heartbeats
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
// Wait for heartbeat byte before send
unsigned char answer = 0;
- status = dc_serial_read(device->port, &answer, 1, NULL);
+ status = dc_iostream_read(device->iostream, &answer, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (device->base.context, "Failed to receive device heartbeat.");
return status;
@@ -359,9 +359,9 @@ 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) dc_serial_sleep(device->port, 16); // 16 ms
+ if (i) dc_iostream_sleep(device->iostream, 16); // 16 ms
- status = dc_serial_write(device->port, command + i, 1, NULL);
+ status = dc_iostream_write(device->iostream, command + i, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -370,10 +370,10 @@ cochran_commander_packet (cochran_commander_device_t *device, dc_event_progress_
if (high_speed && device->layout->baudrate != 9600) {
// Give the DC time to process the command.
- dc_serial_sleep(device->port, 45);
+ dc_iostream_sleep(device->iostream, 45);
// Rates are odd, like 850400 for the EMC, 115200 for commander
- status = dc_serial_configure(device->port, device->layout->baudrate, 8, DC_PARITY_NONE, DC_STOPBITS_TWO, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure(device->iostream, 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 status;
@@ -388,7 +388,7 @@ cochran_commander_packet (cochran_commander_device_t *device, dc_event_progress_
if (len > 1024)
len = 1024;
- status = dc_serial_read (device->port, answer + nbytes, len, NULL);
+ status = dc_iostream_read (device->iostream, answer + nbytes, len, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive data.");
return status;
@@ -523,7 +523,7 @@ cochran_commander_read (cochran_commander_device_t *device, dc_event_progress_t
return DC_STATUS_UNSUPPORTED;
}
- dc_serial_sleep(device->port, 550);
+ dc_iostream_sleep(device->iostream, 550);
// set back to 9600 baud
rc = cochran_commander_serial_setup(device);
@@ -732,11 +732,11 @@ cochran_commander_device_open (dc_device_t **out, dc_context_t *context, const c
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
cochran_commander_device_set_fingerprint((dc_device_t *) device, NULL, 0);
// Open the device.
- status = dc_serial_open (&device->port, device->base.context, name);
+ status = dc_serial_open (&device->iostream, device->base.context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (device->base.context, "Failed to open the serial port.");
goto error_free;
@@ -785,7 +785,7 @@ cochran_commander_device_open (dc_device_t **out, dc_context_t *context, const c
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -799,7 +799,7 @@ cochran_commander_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
diff --git a/src/context-private.h b/src/context-private.h
index 800ef24..793abc3 100644
--- a/src/context-private.h
+++ b/src/context-private.h
@@ -75,19 +75,8 @@ dc_context_hexdump (dc_context_t *context, dc_loglevel_t loglevel, const char *f
dc_custom_io_t*
_dc_context_custom_io (dc_context_t *context);
-#define RETURN_IF_CUSTOM_SERIAL(context, block, function, ...) \
- do { \
- dc_custom_io_t *c = _dc_context_custom_io(context); \
- dc_status_t _rc; \
- if (c) { \
- if (c->serial_##function) \
- _rc = c->serial_##function(c, ##__VA_ARGS__); \
- else \
- _rc = DC_STATUS_SUCCESS; \
- block ;\
- return _rc; \
- } \
- } while (0)
+dc_status_t
+dc_custom_io_serial_open(dc_iostream_t **out, dc_context_t *context, const char *name);
#ifdef __cplusplus
}
diff --git a/src/cressi_edy.c b/src/cressi_edy.c
index 68e13fc..80e4fac 100644
--- a/src/cressi_edy.c
+++ b/src/cressi_edy.c
@@ -55,7 +55,7 @@ typedef struct cressi_edy_layout_t {
typedef struct cressi_edy_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
const cressi_edy_layout_t *layout;
unsigned char fingerprint[SZ_PAGE / 2];
unsigned int model;
@@ -112,7 +112,7 @@ 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.
- status = dc_serial_write (device->port, command + i, 1, NULL);
+ status = dc_iostream_write (device->iostream, command + i, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -120,7 +120,7 @@ cressi_edy_packet (cressi_edy_device_t *device, const unsigned char command[], u
// Receive the echo.
unsigned char echo = 0;
- status = dc_serial_read (device->port, &echo, 1, NULL);
+ status = dc_iostream_read (device->iostream, &echo, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the echo.");
return status;
@@ -135,7 +135,7 @@ cressi_edy_packet (cressi_edy_device_t *device, const unsigned char command[], u
if (asize) {
// Receive the answer of the device.
- status = dc_serial_read (device->port, answer, asize, NULL);
+ status = dc_iostream_read (device->iostream, answer, asize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -165,8 +165,8 @@ cressi_edy_transfer (cressi_edy_device_t *device, const unsigned char command[],
return rc;
// Delay the next attempt.
- dc_serial_sleep (device->port, 300);
- dc_serial_purge (device->port, DC_DIRECTION_INPUT);
+ dc_iostream_sleep (device->iostream, 300);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_INPUT);
}
return DC_STATUS_SUCCESS;
@@ -234,49 +234,49 @@ cressi_edy_device_open (dc_device_t **out, dc_context_t *context, const char *na
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
device->layout = NULL;
device->model = 0;
memset (device->fingerprint, 0, sizeof (device->fingerprint));
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (1200 8N1).
- status = dc_serial_configure (device->port, 1200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 1200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (1000 ms).
- status = dc_serial_set_timeout (device->port, 1000);
+ status = dc_iostream_set_timeout (device->iostream, 1000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Set the DTR line.
- status = dc_serial_set_dtr (device->port, 1);
+ status = dc_iostream_set_dtr (device->iostream, 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);
+ status = dc_iostream_set_rts (device->iostream, 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.
- dc_serial_sleep(device->port, 300);
- dc_serial_purge(device->port, DC_DIRECTION_ALL);
+ dc_iostream_sleep(device->iostream, 300);
+ dc_iostream_purge(device->iostream, DC_DIRECTION_ALL);
// Send the init commands.
cressi_edy_init1 (device);
@@ -290,22 +290,22 @@ cressi_edy_device_open (dc_device_t **out, dc_context_t *context, const char *na
}
// Set the serial communication protocol (4800 8N1).
- status = dc_serial_configure (device->port, 4800, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 4800, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Make sure everything is in a sane state.
- dc_serial_sleep(device->port, 300);
- dc_serial_purge(device->port, DC_DIRECTION_ALL);
+ dc_iostream_sleep(device->iostream, 300);
+ dc_iostream_purge(device->iostream, DC_DIRECTION_ALL);
*out = (dc_device_t*) device;
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -326,7 +326,7 @@ cressi_edy_device_close (dc_device_t *abstract)
}
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
diff --git a/src/cressi_leonardo.c b/src/cressi_leonardo.c
index f21a223..4021288 100644
--- a/src/cressi_leonardo.c
+++ b/src/cressi_leonardo.c
@@ -49,7 +49,7 @@
typedef struct cressi_leonardo_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned char fingerprint[5];
} cressi_leonardo_device_t;
@@ -106,14 +106,14 @@ cressi_leonardo_packet (cressi_leonardo_device_t *device, const unsigned char co
return DC_STATUS_CANCELLED;
// Send the command to the device.
- status = dc_serial_write (device->port, command, csize, NULL);
+ status = dc_iostream_write (device->iostream, command, csize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
}
// Receive the answer of the device.
- status = dc_serial_read (device->port, answer, asize, NULL);
+ status = dc_iostream_read (device->iostream, answer, asize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -156,8 +156,8 @@ cressi_leonardo_transfer (cressi_leonardo_device_t *device, const unsigned char
return rc;
// Discard any garbage bytes.
- dc_serial_sleep (device->port, 100);
- dc_serial_purge (device->port, DC_DIRECTION_INPUT);
+ dc_iostream_sleep (device->iostream, 100);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_INPUT);
}
return rc;
@@ -180,62 +180,62 @@ cressi_leonardo_device_open (dc_device_t **out, dc_context_t *context, const cha
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
memset (device->fingerprint, 0, sizeof (device->fingerprint));
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (115200 8N1).
- status = dc_serial_configure (device->port, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (1000 ms).
- status = dc_serial_set_timeout (device->port, 1000);
+ status = dc_iostream_set_timeout (device->iostream, 1000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Set the RTS line.
- status = dc_serial_set_rts (device->port, 1);
+ status = dc_iostream_set_rts (device->iostream, 1);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the RTS line.");
goto error_close;
}
// Set the DTR line.
- status = dc_serial_set_dtr (device->port, 1);
+ status = dc_iostream_set_dtr (device->iostream, 1);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the DTR line.");
goto error_close;
}
- dc_serial_sleep (device->port, 200);
+ dc_iostream_sleep (device->iostream, 200);
// Clear the DTR line.
- status = dc_serial_set_dtr (device->port, 0);
+ status = dc_iostream_set_dtr (device->iostream, 0);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to clear the DTR line.");
goto error_close;
}
- dc_serial_sleep (device->port, 100);
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_sleep (device->iostream, 100);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
*out = (dc_device_t *) device;
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -249,7 +249,7 @@ cressi_leonardo_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -334,7 +334,7 @@ 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};
- status = dc_serial_write (device->port, command, sizeof (command), NULL);
+ status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -342,7 +342,7 @@ cressi_leonardo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
// Receive the header packet.
unsigned char header[7] = {0};
- status = dc_serial_read (device->port, header, sizeof (header), NULL);
+ status = dc_iostream_read (device->iostream, header, sizeof (header), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -364,7 +364,7 @@ cressi_leonardo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
// Increase the packet size if more data is immediately available.
size_t available = 0;
- status = dc_serial_get_available (device->port, &available);
+ status = dc_iostream_get_available (device->iostream, &available);
if (status == DC_STATUS_SUCCESS && available > len)
len = available;
@@ -373,7 +373,7 @@ cressi_leonardo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
len = SZ_MEMORY - nbytes;
// Read the packet.
- status = dc_serial_read (device->port, data + nbytes, len, NULL);
+ status = dc_iostream_read (device->iostream, data + nbytes, len, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -388,7 +388,7 @@ cressi_leonardo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
// Receive the trailer packet.
unsigned char trailer[4] = {0};
- status = dc_serial_read (device->port, trailer, sizeof (trailer), NULL);
+ status = dc_iostream_read (device->iostream, trailer, sizeof (trailer), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
diff --git a/src/custom.c b/src/custom.c
new file mode 100644
index 0000000..e96ba5f
--- /dev/null
+++ b/src/custom.c
@@ -0,0 +1,263 @@
+/*
+ * libdivecomputer
+ *
+ * Copyright (C) 2017 Jef Driesen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include // malloc, free
+
+#include "custom.h"
+
+#include "iostream-private.h"
+#include "common-private.h"
+#include "context-private.h"
+
+static dc_status_t dc_custom_set_timeout (dc_iostream_t *abstract, int timeout);
+static dc_status_t dc_custom_set_latency (dc_iostream_t *abstract, unsigned int value);
+static dc_status_t dc_custom_set_halfduplex (dc_iostream_t *abstract, unsigned int value);
+static dc_status_t dc_custom_set_break (dc_iostream_t *abstract, unsigned int value);
+static dc_status_t dc_custom_set_dtr (dc_iostream_t *abstract, unsigned int value);
+static dc_status_t dc_custom_set_rts (dc_iostream_t *abstract, unsigned int value);
+static dc_status_t dc_custom_get_lines (dc_iostream_t *abstract, unsigned int *value);
+static dc_status_t dc_custom_get_available (dc_iostream_t *abstract, size_t *value);
+static dc_status_t dc_custom_configure (dc_iostream_t *abstract, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
+static dc_status_t dc_custom_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual);
+static dc_status_t dc_custom_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual);
+static dc_status_t dc_custom_flush (dc_iostream_t *abstract);
+static dc_status_t dc_custom_purge (dc_iostream_t *abstract, dc_direction_t direction);
+static dc_status_t dc_custom_sleep (dc_iostream_t *abstract, unsigned int milliseconds);
+static dc_status_t dc_custom_close (dc_iostream_t *abstract);
+
+typedef struct dc_custom_t {
+ /* Base class. */
+ dc_iostream_t base;
+ /* Internal state. */
+ dc_custom_cbs_t callbacks;
+ void *userdata;
+} dc_custom_t;
+
+static const dc_iostream_vtable_t dc_custom_vtable = {
+ sizeof(dc_custom_t),
+ dc_custom_set_timeout, /* set_timeout */
+ dc_custom_set_latency, /* set_latency */
+ dc_custom_set_halfduplex, /* set_halfduplex */
+ dc_custom_set_break, /* set_break */
+ dc_custom_set_dtr, /* set_dtr */
+ dc_custom_set_rts, /* set_rts */
+ dc_custom_get_lines, /* get_lines */
+ dc_custom_get_available, /* get_received */
+ dc_custom_configure, /* configure */
+ dc_custom_read, /* read */
+ dc_custom_write, /* write */
+ dc_custom_flush, /* flush */
+ dc_custom_purge, /* purge */
+ dc_custom_sleep, /* sleep */
+ dc_custom_close, /* close */
+};
+
+dc_status_t
+dc_custom_open (dc_iostream_t **out, dc_context_t *context, const dc_custom_cbs_t *callbacks, void *userdata)
+{
+ dc_custom_t *custom = NULL;
+
+ if (out == NULL || callbacks == NULL)
+ return DC_STATUS_INVALIDARGS;
+
+ INFO (context, "Open: custom");
+
+ // Allocate memory.
+ custom = (dc_custom_t *) dc_iostream_allocate (context, &dc_custom_vtable);
+ if (custom == NULL) {
+ ERROR (context, "Failed to allocate memory.");
+ return DC_STATUS_NOMEMORY;
+ }
+
+ custom->callbacks = *callbacks;
+ custom->userdata = userdata;
+
+ *out = (dc_iostream_t *) custom;
+
+ return DC_STATUS_SUCCESS;
+}
+
+static dc_status_t
+dc_custom_set_timeout (dc_iostream_t *abstract, int timeout)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+
+ if (custom->callbacks.set_timeout == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ return custom->callbacks.set_timeout (custom->userdata, timeout);
+}
+
+static dc_status_t
+dc_custom_set_latency (dc_iostream_t *abstract, unsigned int value)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+
+ if (custom->callbacks.set_latency == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ return custom->callbacks.set_latency (custom->userdata, value);
+}
+
+static dc_status_t
+dc_custom_set_halfduplex (dc_iostream_t *abstract, unsigned int value)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+
+ if (custom->callbacks.set_halfduplex == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ return custom->callbacks.set_halfduplex (custom->userdata, value);
+}
+
+static dc_status_t
+dc_custom_set_break (dc_iostream_t *abstract, unsigned int value)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+
+ if (custom->callbacks.set_break == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ return custom->callbacks.set_break (custom->userdata, value);
+}
+
+static dc_status_t
+dc_custom_set_dtr (dc_iostream_t *abstract, unsigned int value)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+
+ if (custom->callbacks.set_dtr == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ return custom->callbacks.set_dtr (custom->userdata, value);
+}
+
+static dc_status_t
+dc_custom_set_rts (dc_iostream_t *abstract, unsigned int value)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+
+ if (custom->callbacks.set_rts == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ return custom->callbacks.set_rts (custom->userdata, value);
+}
+
+static dc_status_t
+dc_custom_get_lines (dc_iostream_t *abstract, unsigned int *value)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+
+ if (custom->callbacks.get_lines == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ return custom->callbacks.get_lines (custom->userdata, value);
+}
+
+static dc_status_t
+dc_custom_get_available (dc_iostream_t *abstract, size_t *value)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+
+ if (custom->callbacks.get_available == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ return custom->callbacks.get_available (custom->userdata, value);
+}
+
+static dc_status_t
+dc_custom_configure (dc_iostream_t *abstract, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+
+ if (custom->callbacks.configure == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ return custom->callbacks.configure (custom->userdata, baudrate, databits, parity, stopbits, flowcontrol);
+}
+
+static dc_status_t
+dc_custom_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+
+ if (custom->callbacks.read == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ return custom->callbacks.read (custom->userdata, data, size, actual);
+}
+
+static dc_status_t
+dc_custom_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+
+ if (custom->callbacks.write == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ return custom->callbacks.write (custom->userdata, data, size, actual);
+}
+
+static dc_status_t
+dc_custom_flush (dc_iostream_t *abstract)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+
+ if (custom->callbacks.flush == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ return custom->callbacks.flush (custom->userdata);
+}
+
+static dc_status_t
+dc_custom_purge (dc_iostream_t *abstract, dc_direction_t direction)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+
+ if (custom->callbacks.purge == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ return custom->callbacks.purge (custom->userdata, direction);
+}
+
+static dc_status_t
+dc_custom_sleep (dc_iostream_t *abstract, unsigned int milliseconds)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+
+ if (custom->callbacks.sleep == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ return custom->callbacks.sleep (custom->userdata, milliseconds);
+}
+
+static dc_status_t
+dc_custom_close (dc_iostream_t *abstract)
+{
+ dc_status_t status = DC_STATUS_SUCCESS;
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+
+ if (custom->callbacks.close) {
+ status = custom->callbacks.close (custom->userdata);
+ }
+
+ return status;
+}
diff --git a/src/custom.h b/src/custom.h
new file mode 100644
index 0000000..f062cd3
--- /dev/null
+++ b/src/custom.h
@@ -0,0 +1,67 @@
+/*
+ * libdivecomputer
+ *
+ * Copyright (C) 2017 Jef Driesen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#ifndef DC_CUSTOM_H
+#define DC_CUSTOM_H
+
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct dc_custom_cbs_t {
+ dc_status_t (*set_timeout) (void *userdata, int timeout);
+ dc_status_t (*set_latency) (void *userdata, unsigned int value);
+ dc_status_t (*set_halfduplex) (void *userdata, unsigned int value);
+ dc_status_t (*set_break) (void *userdata, unsigned int value);
+ dc_status_t (*set_dtr) (void *userdata, unsigned int value);
+ dc_status_t (*set_rts) (void *userdata, unsigned int value);
+ dc_status_t (*get_lines) (void *userdata, unsigned int *value);
+ dc_status_t (*get_available) (void *userdata, size_t *value);
+ dc_status_t (*configure) (void *userdata, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
+ dc_status_t (*read) (void *userdata, void *data, size_t size, size_t *actual);
+ dc_status_t (*write) (void *userdata, const void *data, size_t size, size_t *actual);
+ dc_status_t (*flush) (void *userdata);
+ dc_status_t (*purge) (void *userdata, dc_direction_t direction);
+ dc_status_t (*sleep) (void *userdata, unsigned int milliseconds);
+ dc_status_t (*close) (void *userdata);
+} dc_custom_cbs_t;
+
+/**
+ * Create a custom I/O stream.
+ *
+ * @param[out] iostream A location to store the custom I/O stream.
+ * @param[in] context A valid context object.
+ * @param[in] callbacks The callback functions to call.
+ * @param[in] userdata User data to pass to the callback functions.
+ * @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
+ * on failure.
+ */
+dc_status_t
+dc_custom_open (dc_iostream_t **iostream, dc_context_t *context, const dc_custom_cbs_t *callbacks, void *userdata);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* DC_CUSTOM_H */
diff --git a/src/custom_io.c b/src/custom_io.c
new file mode 100644
index 0000000..dd1adfa
--- /dev/null
+++ b/src/custom_io.c
@@ -0,0 +1,231 @@
+/*
+ * libdivecomputer
+ *
+ * Copyright (C) 2017 Jef Driesen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include // malloc, free
+
+#include
+
+#include "iostream-private.h"
+#include "common-private.h"
+#include "context-private.h"
+
+/*
+ * This is shamelessly stolen from src/custom.c, to make it
+ * work with the subsurface custom_io model.
+ */
+typedef struct dc_custom_t {
+ /* Base class. */
+ dc_iostream_t base;
+ /* Internal state. */
+ dc_context_t *context;
+} dc_custom_t;
+
+static dc_status_t
+dc_custom_set_timeout (dc_iostream_t *abstract, int timeout)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+ dc_custom_io_t *io = _dc_context_custom_io(custom->context);
+
+ if (!io->serial_set_timeout)
+ return DC_STATUS_SUCCESS;
+
+ return io->serial_set_timeout(io, timeout);
+}
+
+static dc_status_t
+dc_custom_set_latency (dc_iostream_t *abstract, unsigned int value)
+{
+ return DC_STATUS_SUCCESS;
+}
+
+static dc_status_t
+dc_custom_set_halfduplex (dc_iostream_t *abstract, unsigned int value)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+ dc_custom_io_t *io = _dc_context_custom_io(custom->context);
+
+ if (!io->serial_set_halfduplex)
+ return DC_STATUS_SUCCESS;
+
+ return io->serial_set_halfduplex(io, value);
+}
+
+static dc_status_t
+dc_custom_set_break (dc_iostream_t *abstract, unsigned int value)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+ dc_custom_io_t *io = _dc_context_custom_io(custom->context);
+
+ if (!io->serial_set_break)
+ return DC_STATUS_SUCCESS;
+
+ return io->serial_set_break(io, value);
+}
+
+static dc_status_t
+dc_custom_set_dtr (dc_iostream_t *abstract, unsigned int value)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+ dc_custom_io_t *io = _dc_context_custom_io(custom->context);
+
+ if (!io->serial_set_dtr)
+ return DC_STATUS_SUCCESS;
+
+ return io->serial_set_dtr(io, value);
+}
+
+static dc_status_t
+dc_custom_set_rts (dc_iostream_t *abstract, unsigned int value)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+ dc_custom_io_t *io = _dc_context_custom_io(custom->context);
+
+ if (!io->serial_set_rts)
+ return DC_STATUS_SUCCESS;
+
+ return io->serial_set_rts(io, value);
+}
+
+static dc_status_t
+dc_custom_get_lines (dc_iostream_t *abstract, unsigned int *value)
+{
+ return DC_STATUS_SUCCESS;
+}
+
+static dc_status_t
+dc_custom_get_available (dc_iostream_t *abstract, size_t *value)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+ dc_custom_io_t *io = _dc_context_custom_io(custom->context);
+
+ if (!io->serial_get_available)
+ return DC_STATUS_SUCCESS;
+
+ return io->serial_get_available(io, value);
+}
+
+static dc_status_t
+dc_custom_configure (dc_iostream_t *abstract, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+ dc_custom_io_t *io = _dc_context_custom_io(custom->context);
+
+ if (!io->serial_configure)
+ return DC_STATUS_SUCCESS;
+
+ return io->serial_configure(io, baudrate, databits, parity, stopbits, flowcontrol);
+}
+
+static dc_status_t
+dc_custom_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+ dc_custom_io_t *io = _dc_context_custom_io(custom->context);
+
+ if (!io->serial_read)
+ return DC_STATUS_SUCCESS;
+
+ return io->serial_read(io, data, size, actual);
+}
+
+static dc_status_t
+dc_custom_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+ dc_custom_io_t *io = _dc_context_custom_io(custom->context);
+
+ if (!io->serial_write)
+ return DC_STATUS_SUCCESS;
+
+ return io->serial_write(io, data, size, actual);
+}
+
+static dc_status_t
+dc_custom_flush (dc_iostream_t *abstract)
+{
+ return DC_STATUS_SUCCESS;
+}
+
+static dc_status_t
+dc_custom_purge (dc_iostream_t *abstract, dc_direction_t direction)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+ dc_custom_io_t *io = _dc_context_custom_io(custom->context);
+
+ if (!io->serial_purge)
+ return DC_STATUS_SUCCESS;
+
+ return io->serial_purge(io, direction);
+}
+
+static dc_status_t
+dc_custom_sleep (dc_iostream_t *abstract, unsigned int milliseconds)
+{
+ return DC_STATUS_SUCCESS;
+}
+
+static dc_status_t
+dc_custom_close (dc_iostream_t *abstract)
+{
+ dc_custom_t *custom = (dc_custom_t *) abstract;
+ dc_custom_io_t *io = _dc_context_custom_io(custom->context);
+
+ if (!io->serial_close)
+ return DC_STATUS_SUCCESS;
+
+ return io->serial_close(io);
+}
+
+static const dc_iostream_vtable_t dc_custom_vtable = {
+ sizeof(dc_custom_t),
+ dc_custom_set_timeout, /* set_timeout */
+ dc_custom_set_latency, /* set_latency */
+ dc_custom_set_halfduplex, /* set_halfduplex */
+ dc_custom_set_break, /* set_break */
+ dc_custom_set_dtr, /* set_dtr */
+ dc_custom_set_rts, /* set_rts */
+ dc_custom_get_lines, /* get_lines */
+ dc_custom_get_available, /* get_received */
+ dc_custom_configure, /* configure */
+ dc_custom_read, /* read */
+ dc_custom_write, /* write */
+ dc_custom_flush, /* flush */
+ dc_custom_purge, /* purge */
+ dc_custom_sleep, /* sleep */
+ dc_custom_close, /* close */
+};
+
+dc_status_t
+dc_custom_io_serial_open(dc_iostream_t **out, dc_context_t *context, const char *name)
+{
+ dc_custom_io_t *io = _dc_context_custom_io(context);
+ dc_custom_t *custom;
+
+ custom = (dc_custom_t *) dc_iostream_allocate (context, &dc_custom_vtable);
+ if (!custom) {
+ ERROR (context, "Failed to allocate memory.");
+ return DC_STATUS_NOMEMORY;
+ }
+
+ custom->context = context;
+ *out = (dc_iostream_t *) custom;
+ return io->serial_open(io, context, name);
+}
diff --git a/src/diverite_nitekq.c b/src/diverite_nitekq.c
index 8c8c442..8524b56 100644
--- a/src/diverite_nitekq.c
+++ b/src/diverite_nitekq.c
@@ -51,7 +51,7 @@
typedef struct diverite_nitekq_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned char version[32];
unsigned char fingerprint[SZ_LOGBOOK];
} diverite_nitekq_device_t;
@@ -87,7 +87,7 @@ diverite_nitekq_send (diverite_nitekq_device_t *device, unsigned char cmd)
// Send the command.
unsigned char command[] = {cmd};
- status = dc_serial_write (device->port, command, sizeof (command), NULL);
+ status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -104,7 +104,7 @@ diverite_nitekq_receive (diverite_nitekq_device_t *device, unsigned char data[],
dc_device_t *abstract = (dc_device_t *) device;
// Read the answer.
- status = dc_serial_read (device->port, data, size, NULL);
+ status = dc_iostream_read (device->iostream, data, size, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -112,7 +112,7 @@ diverite_nitekq_receive (diverite_nitekq_device_t *device, unsigned char data[],
// Read the checksum.
unsigned char checksum[2] = {0};
- status = dc_serial_read (device->port, checksum, sizeof (checksum), NULL);
+ status = dc_iostream_read (device->iostream, checksum, sizeof (checksum), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the checksum.");
return status;
@@ -130,14 +130,14 @@ diverite_nitekq_handshake (diverite_nitekq_device_t *device)
// Send the command.
unsigned char command[] = {HANDSHAKE};
- status = dc_serial_write (device->port, command, sizeof (command), NULL);
+ status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
}
// Read the answer.
- status = dc_serial_read (device->port, device->version, sizeof (device->version), NULL);
+ status = dc_iostream_read (device->iostream, device->version, sizeof (device->version), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -164,33 +164,33 @@ diverite_nitekq_device_open (dc_device_t **out, dc_context_t *context, const cha
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
memset (device->fingerprint, 0, sizeof (device->fingerprint));
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (9600 8N1).
- status = dc_serial_configure (device->port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (1000ms).
- status = dc_serial_set_timeout (device->port, 1000);
+ status = dc_iostream_set_timeout (device->iostream, 1000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Make sure everything is in a sane state.
- dc_serial_sleep (device->port, 100);
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_sleep (device->iostream, 100);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
// Perform the handshaking.
status = diverite_nitekq_handshake (device);
@@ -204,7 +204,7 @@ diverite_nitekq_device_open (dc_device_t **out, dc_context_t *context, const cha
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -225,7 +225,7 @@ diverite_nitekq_device_close (dc_device_t *abstract)
}
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
diff --git a/src/divesystem_idive.c b/src/divesystem_idive.c
index 8a8f1ae..46ecb34 100644
--- a/src/divesystem_idive.c
+++ b/src/divesystem_idive.c
@@ -69,7 +69,7 @@ typedef struct divesystem_idive_commands_t {
typedef struct divesystem_idive_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned char fingerprint[4];
unsigned int model;
} divesystem_idive_device_t;
@@ -131,41 +131,41 @@ divesystem_idive_device_open (dc_device_t **out, dc_context_t *context, const ch
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
memset (device->fingerprint, 0, sizeof (device->fingerprint));
device->model = model;
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (115200 8N1).
- status = dc_serial_configure (device->port, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (1000ms).
- status = dc_serial_set_timeout (device->port, 1000);
+ status = dc_iostream_set_timeout (device->iostream, 1000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Make sure everything is in a sane state.
- dc_serial_sleep (device->port, 300);
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_sleep (device->iostream, 300);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
*out = (dc_device_t *) device;
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -180,7 +180,7 @@ divesystem_idive_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -229,7 +229,7 @@ divesystem_idive_send (divesystem_idive_device_t *device, const unsigned char co
packet[csize + 3] = (crc ) & 0xFF;
// Send the data packet.
- status = dc_serial_write (device->port, packet, csize + 4, NULL);
+ status = dc_iostream_write (device->iostream, packet, csize + 4, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -253,7 +253,7 @@ divesystem_idive_receive (divesystem_idive_device_t *device, unsigned char answe
// Read the packet start byte.
while (1) {
- status = dc_serial_read (device->port, packet + 0, 1, NULL);
+ status = dc_iostream_read (device->iostream, packet + 0, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the packet start byte.");
return status;
@@ -264,7 +264,7 @@ divesystem_idive_receive (divesystem_idive_device_t *device, unsigned char answe
}
// Read the packet length.
- status = dc_serial_read (device->port, packet + 1, 1, NULL);
+ status = dc_iostream_read (device->iostream, packet + 1, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the packet length.");
return status;
@@ -277,7 +277,7 @@ divesystem_idive_receive (divesystem_idive_device_t *device, unsigned char answe
}
// Read the packet payload and checksum.
- status = dc_serial_read (device->port, packet + 2, len + 2, NULL);
+ status = dc_iostream_read (device->iostream, packet + 2, len + 2, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the packet payload and checksum.");
return status;
@@ -383,7 +383,7 @@ divesystem_idive_transfer (divesystem_idive_device_t *device, const unsigned cha
break;
// Delay the next attempt.
- dc_serial_sleep (device->port, 100);
+ dc_iostream_sleep (device->iostream, 100);
}
if (errorcode) {
diff --git a/src/divesystem_idive_parser.c b/src/divesystem_idive_parser.c
index 24f7e53..413d7c4 100644
--- a/src/divesystem_idive_parser.c
+++ b/src/divesystem_idive_parser.c
@@ -230,8 +230,10 @@ divesystem_idive_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
*((dc_divemode_t *) value) = DC_DIVEMODE_OC;
break;
case SCR:
+ *((dc_divemode_t *) value) = DC_DIVEMODE_SCR;
+ break;
case CCR:
- *((dc_divemode_t *) value) = DC_DIVEMODE_CC;
+ *((dc_divemode_t *) value) = DC_DIVEMODE_CCR;
break;
case GAUGE:
*((dc_divemode_t *) value) = DC_DIVEMODE_GAUGE;
diff --git a/src/hw_frog.c b/src/hw_frog.c
index 83ee998..e2bec3b 100644
--- a/src/hw_frog.c
+++ b/src/hw_frog.c
@@ -55,7 +55,7 @@
typedef struct hw_frog_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned char fingerprint[5];
} hw_frog_device_t;
@@ -114,7 +114,7 @@ hw_frog_transfer (hw_frog_device_t *device,
// Send the command.
unsigned char command[1] = {cmd};
- status = dc_serial_write (device->port, command, sizeof (command), NULL);
+ status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -123,7 +123,7 @@ hw_frog_transfer (hw_frog_device_t *device,
if (cmd != INIT && cmd != HEADER) {
// Read the echo.
unsigned char answer[1] = {0};
- status = dc_serial_read (device->port, answer, sizeof (answer), NULL);
+ status = dc_iostream_read (device->iostream, answer, sizeof (answer), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the echo.");
return status;
@@ -138,7 +138,7 @@ hw_frog_transfer (hw_frog_device_t *device,
if (input) {
// Send the input data packet.
- status = dc_serial_write (device->port, input, isize, NULL);
+ status = dc_iostream_write (device->iostream, input, isize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the data packet.");
return status;
@@ -153,7 +153,7 @@ hw_frog_transfer (hw_frog_device_t *device,
// Increase the packet size if more data is immediately available.
size_t available = 0;
- status = dc_serial_get_available (device->port, &available);
+ status = dc_iostream_get_available (device->iostream, &available);
if (status == DC_STATUS_SUCCESS && available > len)
len = available;
@@ -162,7 +162,7 @@ hw_frog_transfer (hw_frog_device_t *device,
len = osize - nbytes;
// Read the packet.
- status = dc_serial_read (device->port, output + nbytes, len, NULL);
+ status = dc_iostream_read (device->iostream, output + nbytes, len, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -181,7 +181,7 @@ hw_frog_transfer (hw_frog_device_t *device,
if (cmd != EXIT) {
// Read the ready byte.
unsigned char answer[1] = {0};
- status = dc_serial_read (device->port, answer, sizeof (answer), NULL);
+ status = dc_iostream_read (device->iostream, answer, sizeof (answer), NULL);
if (status != sizeof (answer)) {
ERROR (abstract->context, "Failed to receive the ready byte.");
return status;
@@ -215,33 +215,33 @@ hw_frog_device_open (dc_device_t **out, dc_context_t *context, const char *name)
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
memset (device->fingerprint, 0, sizeof (device->fingerprint));
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (115200 8N1).
- status = dc_serial_configure (device->port, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (3000ms).
- status = dc_serial_set_timeout (device->port, 3000);
+ status = dc_iostream_set_timeout (device->iostream, 3000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Make sure everything is in a sane state.
- dc_serial_sleep (device->port, 300);
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_sleep (device->iostream, 300);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
// Send the init command.
status = hw_frog_transfer (device, NULL, INIT, NULL, 0, NULL, 0);
@@ -255,7 +255,7 @@ hw_frog_device_open (dc_device_t **out, dc_context_t *context, const char *name)
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -277,7 +277,7 @@ hw_frog_device_close (dc_device_t *abstract)
}
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
diff --git a/src/hw_ostc.c b/src/hw_ostc.c
index 87c2b1d..36d6080 100644
--- a/src/hw_ostc.c
+++ b/src/hw_ostc.c
@@ -58,7 +58,7 @@
typedef struct hw_ostc_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned char fingerprint[5];
} hw_ostc_device_t;
@@ -96,7 +96,7 @@ hw_ostc_send (hw_ostc_device_t *device, unsigned char cmd, unsigned int echo)
// Send the command.
unsigned char command[1] = {cmd};
- status = dc_serial_write (device->port, command, sizeof (command), NULL);
+ status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -105,7 +105,7 @@ hw_ostc_send (hw_ostc_device_t *device, unsigned char cmd, unsigned int echo)
if (echo) {
// Read the echo.
unsigned char answer[1] = {0};
- status = dc_serial_read (device->port, answer, sizeof (answer), NULL);
+ status = dc_iostream_read (device->iostream, answer, sizeof (answer), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the echo.");
return status;
@@ -139,40 +139,40 @@ hw_ostc_device_open (dc_device_t **out, dc_context_t *context, const char *name)
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
memset (device->fingerprint, 0, sizeof (device->fingerprint));
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (115200 8N1).
- status = dc_serial_configure (device->port, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data.
- status = dc_serial_set_timeout (device->port, 4000);
+ status = dc_iostream_set_timeout (device->iostream, 4000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Make sure everything is in a sane state.
- dc_serial_sleep (device->port, 100);
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_sleep (device->iostream, 100);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
*out = (dc_device_t*) device;
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -187,7 +187,7 @@ hw_ostc_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -232,7 +232,7 @@ hw_ostc_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
// Send the command.
unsigned char command[1] = {'a'};
- status = dc_serial_write (device->port, command, sizeof (command), NULL);
+ status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -240,7 +240,7 @@ hw_ostc_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
// Read the header.
unsigned char header[SZ_HEADER] = {0};
- status = dc_serial_read (device->port, header, sizeof (header), NULL);
+ status = dc_iostream_read (device->iostream, header, sizeof (header), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the header.");
return status;
@@ -286,7 +286,7 @@ hw_ostc_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
// Increase the packet size if more data is immediately available.
size_t available = 0;
- status = dc_serial_get_available (device->port, &available);
+ status = dc_iostream_get_available (device->iostream, &available);
if (status == DC_STATUS_SUCCESS && available > len)
len = available;
@@ -295,7 +295,7 @@ hw_ostc_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
len = size - nbytes;
// Read the packet.
- status = dc_serial_read (device->port, data + nbytes, len, NULL);
+ status = dc_iostream_read (device->iostream, data + nbytes, len, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -369,7 +369,7 @@ hw_ostc_device_md2hash (dc_device_t *abstract, unsigned char data[], unsigned in
return rc;
// Read the answer.
- status = dc_serial_read (device->port, data, SZ_MD2HASH, NULL);
+ status = dc_iostream_read (device->iostream, data, SZ_MD2HASH, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -399,7 +399,7 @@ hw_ostc_device_timesync (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};
- status = dc_serial_write (device->port, packet, sizeof (packet), NULL);
+ status = dc_iostream_write (device->iostream, packet, sizeof (packet), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the data packet.");
return status;
@@ -435,7 +435,7 @@ hw_ostc_device_eeprom_read (dc_device_t *abstract, unsigned int bank, unsigned c
return rc;
// Read the answer.
- status = dc_serial_read (device->port, data, SZ_EEPROM, NULL);
+ status = dc_iostream_read (device->iostream, data, SZ_EEPROM, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -556,7 +556,7 @@ 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};
- status = dc_serial_read (device->port, raw, 1, NULL);
+ status = dc_iostream_read (device->iostream, raw, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the packet.");
return status;
@@ -574,7 +574,7 @@ hw_ostc_device_screenshot (dc_device_t *abstract, dc_buffer_t *buffer, hw_ostc_f
count &= 0x3F;
} else {
// Color pixel.
- status = dc_serial_read (device->port, raw + 1, 2, NULL);
+ status = dc_iostream_read (device->iostream, raw + 1, 2, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the packet.");
return status;
@@ -774,7 +774,7 @@ hw_ostc_firmware_setup_internal (hw_ostc_device_t *device)
// Send the command.
unsigned char command[1] = {0xC1};
- status = dc_serial_write (device->port, command, sizeof (command), NULL);
+ status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -782,7 +782,7 @@ hw_ostc_firmware_setup_internal (hw_ostc_device_t *device)
// Read the response.
unsigned char answer[2] = {0};
- status = dc_serial_read (device->port, answer, sizeof (answer), NULL);
+ status = dc_iostream_read (device->iostream, answer, sizeof (answer), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the response.");
return status;
@@ -825,7 +825,7 @@ hw_ostc_firmware_write_internal (hw_ostc_device_t *device, unsigned char *data,
dc_device_t *abstract = (dc_device_t *) device;
// Send the packet.
- status = dc_serial_write (device->port, data, size, NULL);
+ status = dc_iostream_write (device->iostream, data, size, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the packet.");
return status;
@@ -833,7 +833,7 @@ hw_ostc_firmware_write_internal (hw_ostc_device_t *device, unsigned char *data,
// Read the response.
unsigned char answer[1] = {0};
- status = dc_serial_read (device->port, answer, sizeof (answer), NULL);
+ status = dc_iostream_read (device->iostream, answer, sizeof (answer), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the response.");
return status;
@@ -905,13 +905,13 @@ 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.
- dc_serial_set_timeout (device->port, 300);
+ dc_iostream_set_timeout (device->iostream, 300);
// Setup the bootloader.
const unsigned int baudrates[] = {19200, 115200};
for (unsigned int i = 0; i < C_ARRAY_SIZE(baudrates); ++i) {
// Adjust the baudrate.
- rc = dc_serial_configure (device->port, baudrates[i], 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ rc = dc_iostream_configure (device->iostream, 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);
@@ -931,7 +931,7 @@ hw_ostc_device_fwupdate (dc_device_t *abstract, const char *filename)
}
// Increase the timeout again.
- dc_serial_set_timeout (device->port, 1000);
+ dc_iostream_set_timeout (device->iostream, 1000);
// Enable progress notifications.
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c
index 7ce7fd5..e240342 100644
--- a/src/hw_ostc3.c
+++ b/src/hw_ostc3.c
@@ -91,7 +91,7 @@ typedef enum hw_ostc3_state_t {
typedef struct hw_ostc3_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned int hardware;
unsigned int feature;
unsigned int model;
@@ -197,7 +197,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
// Send the command.
unsigned char command[1] = {cmd};
- status = dc_serial_write (device->port, command, sizeof (command), NULL);
+ status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -205,7 +205,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
// Read the echo.
unsigned char echo[1] = {0};
- status = dc_serial_read (device->port, echo, sizeof (echo), NULL);
+ status = dc_iostream_read (device->iostream, echo, sizeof (echo), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the echo.");
return status;
@@ -234,7 +234,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
len = isize - nbytes;
// Write the packet.
- status = dc_serial_write (device->port, input + nbytes, len, NULL);
+ status = dc_iostream_write (device->iostream, input + nbytes, len, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the data packet.");
return status;
@@ -258,7 +258,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
// Increase the packet size if more data is immediately available.
size_t available = 0;
- status = dc_serial_get_available (device->port, &available);
+ status = dc_iostream_get_available (device->iostream, &available);
if (status == DC_STATUS_SUCCESS && available > len)
len = available;
@@ -267,7 +267,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
len = osize - nbytes;
// Read the packet.
- status = dc_serial_read (device->port, output + nbytes, len, NULL);
+ status = dc_iostream_read (device->iostream, output + nbytes, len, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -287,18 +287,18 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
unsigned int count = delay / 100;
for (unsigned int i = 0; i < count; ++i) {
size_t available = 0;
- status = dc_serial_get_available (device->port, &available);
+ status = dc_iostream_get_available (device->iostream, &available);
if (status == DC_STATUS_SUCCESS && available > 0)
break;
- dc_serial_sleep (device->port, 100);
+ dc_iostream_sleep (device->iostream, 100);
}
}
if (cmd != EXIT) {
// Read the ready byte.
unsigned char answer[1] = {0};
- status = dc_serial_read (device->port, answer, sizeof (answer), NULL);
+ status = dc_iostream_read (device->iostream, answer, sizeof (answer), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the ready byte.");
return status;
@@ -332,36 +332,36 @@ hw_ostc3_device_open (dc_device_t **out, dc_context_t *context, const char *name
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
device->hardware = INVALID;
device->feature = 0;
device->model = 0;
memset (device->fingerprint, 0, sizeof (device->fingerprint));
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (115200 8N1).
- status = dc_serial_configure (device->port, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (3000ms).
- status = dc_serial_set_timeout (device->port, 3000);
+ status = dc_iostream_set_timeout (device->iostream, 3000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Make sure everything is in a sane state.
- dc_serial_sleep (device->port, 300);
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_sleep (device->iostream, 300);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
device->state = OPEN;
@@ -370,7 +370,7 @@ hw_ostc3_device_open (dc_device_t **out, dc_context_t *context, const char *name
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -434,17 +434,17 @@ hw_ostc3_device_init_service (hw_ostc3_device_t *device)
unsigned char output[5];
// We cant use hw_ostc3_transfer here, due to the different echos
- status = dc_serial_write (device->port, command, sizeof (command), NULL);
+ status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to send the command.");
return status;
}
// Give the device some time to enter service mode
- dc_serial_sleep (device->port, 100);
+ dc_iostream_sleep (device->iostream, 100);
// Read the response
- status = dc_serial_read (device->port, output, sizeof (output), NULL);
+ status = dc_iostream_read (device->iostream, output, sizeof (output), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to receive the echo.");
return status;
@@ -532,7 +532,7 @@ hw_ostc3_device_close (dc_device_t *abstract)
}
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -727,6 +727,11 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi
if (firmware < 93)
length -= 3;
}
+ if (length < RB_LOGBOOK_SIZE_FULL) {
+ ERROR (abstract->context, "Invalid profile length (%u bytes).", length);
+ free (header);
+ return DC_STATUS_DATAFORMAT;
+ }
// Check the fingerprint data.
if (memcmp (header + offset + logbook->fingerprint, device->fingerprint, sizeof (device->fingerprint)) == 0)
@@ -789,6 +794,26 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi
return rc;
}
+ // Detect invalid profile data.
+ unsigned int delta = device->hardware == OSTC4 ? 3 : 0;
+ if (length < RB_LOGBOOK_SIZE_FULL + 2 ||
+ profile[length - 2] != 0xFD || profile[length - 1] != 0xFD) {
+ // A valid profile should have at least a correct 2 byte
+ // end-of-profile marker.
+ WARNING (abstract->context, "Invalid profile end marker detected!");
+ length = RB_LOGBOOK_SIZE_FULL;
+ } else if (length == RB_LOGBOOK_SIZE_FULL + 2) {
+ // A profile containing only the 2 byte end-of-profile
+ // marker is considered a valid empty profile.
+ } else if (length < RB_LOGBOOK_SIZE_FULL + 5 + 2 ||
+ array_uint24_le (profile + RB_LOGBOOK_SIZE_FULL) + delta != array_uint24_le (profile + 9)) {
+ // If there is more data available, then there should be a
+ // valid profile header containing a length matching the
+ // length in the dive header.
+ WARNING (abstract->context, "Invalid profile header detected.");
+ length = RB_LOGBOOK_SIZE_FULL;
+ }
+
if (callback && !callback (profile, length, profile + 12, sizeof (device->fingerprint), userdata))
break;
}
diff --git a/src/hw_ostc_parser.c b/src/hw_ostc_parser.c
index ed5c824..6b065a9 100644
--- a/src/hw_ostc_parser.c
+++ b/src/hw_ostc_parser.c
@@ -65,6 +65,7 @@
#define OSTC3_CC 1
#define OSTC3_GAUGE 2
#define OSTC3_APNEA 3
+#define OSTC3_PSCR 4
#define OSTC3_ZHL16 0
#define OSTC3_ZHL16_GF 1
@@ -548,8 +549,10 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
break;
case OSTC_ZHL16_CC:
case OSTC_ZHL16_CC_GF:
+ *((dc_divemode_t *) value) = DC_DIVEMODE_CCR;
+ break;
case OSTC_PSCR_GF:
- *((dc_divemode_t *) value) = DC_DIVEMODE_CC;
+ *((dc_divemode_t *) value) = DC_DIVEMODE_SCR;
break;
default:
return DC_STATUS_DATAFORMAT;
@@ -572,7 +575,7 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
*((dc_divemode_t *) value) = DC_DIVEMODE_OC;
break;
case OSTC3_CC:
- *((dc_divemode_t *) value) = DC_DIVEMODE_CC;
+ *((dc_divemode_t *) value) = DC_DIVEMODE_CCR;
break;
case OSTC3_GAUGE:
*((dc_divemode_t *) value) = DC_DIVEMODE_GAUGE;
@@ -580,6 +583,9 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
case OSTC3_APNEA:
*((dc_divemode_t *) value) = DC_DIVEMODE_FREEDIVE;
break;
+ case OSTC3_PSCR:
+ *((dc_divemode_t *) value) = DC_DIVEMODE_SCR;
+ break;
default:
return DC_STATUS_DATAFORMAT;
}
@@ -685,6 +691,13 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
unsigned int header = parser->header;
const hw_ostc_layout_t *layout = parser->layout;
+ // Exit if no profile data available.
+ if (size == header || (size == header + 2 &&
+ data[header] == 0xFD && data[header + 1] == 0xFD)) {
+ parser->cached = PROFILE;
+ return DC_STATUS_SUCCESS;
+ }
+
// Check the header length.
if (version == 0x23 || version == 0x24) {
if (size < header + 5) {
diff --git a/src/iostream-private.h b/src/iostream-private.h
new file mode 100644
index 0000000..7f7be84
--- /dev/null
+++ b/src/iostream-private.h
@@ -0,0 +1,86 @@
+/*
+ * libdivecomputer
+ *
+ * Copyright (C) 2016 Jef Driesen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#ifndef DC_IOSTREAM_PRIVATE_H
+#define DC_IOSTREAM_PRIVATE_H
+
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct dc_iostream_vtable_t dc_iostream_vtable_t;
+
+struct dc_iostream_t {
+ const dc_iostream_vtable_t *vtable;
+ dc_context_t *context;
+};
+
+struct dc_iostream_vtable_t {
+ size_t size;
+
+ dc_status_t (*set_timeout) (dc_iostream_t *iostream, int timeout);
+
+ dc_status_t (*set_latency) (dc_iostream_t *iostream, unsigned int value);
+
+ dc_status_t (*set_halfduplex) (dc_iostream_t *iostream, unsigned int value);
+
+ dc_status_t (*set_break) (dc_iostream_t *iostream, unsigned int value);
+
+ dc_status_t (*set_dtr) (dc_iostream_t *iostream, unsigned int value);
+
+ dc_status_t (*set_rts) (dc_iostream_t *iostream, unsigned int value);
+
+ dc_status_t (*get_lines) (dc_iostream_t *iostream, unsigned int *value);
+
+ dc_status_t (*get_available) (dc_iostream_t *iostream, size_t *value);
+
+ dc_status_t (*configure) (dc_iostream_t *iostream, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
+
+ dc_status_t (*read) (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
+
+ dc_status_t (*write) (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
+
+ dc_status_t (*flush) (dc_iostream_t *iostream);
+
+ dc_status_t (*purge) (dc_iostream_t *iostream, dc_direction_t direction);
+
+ dc_status_t (*sleep) (dc_iostream_t *iostream, unsigned int milliseconds);
+
+ dc_status_t (*close) (dc_iostream_t *iostream);
+};
+
+dc_iostream_t *
+dc_iostream_allocate (dc_context_t *context, const dc_iostream_vtable_t *vtable);
+
+void
+dc_iostream_deallocate (dc_iostream_t *iostream);
+
+int
+dc_iostream_isinstance (dc_iostream_t *iostream, const dc_iostream_vtable_t *vtable);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* DC_IOSTREAM_PRIVATE_H */
diff --git a/src/iostream.c b/src/iostream.c
new file mode 100644
index 0000000..e6c40ea
--- /dev/null
+++ b/src/iostream.c
@@ -0,0 +1,254 @@
+/*
+ * libdivecomputer
+ *
+ * Copyright (C) 2016 Jef Driesen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include
+#include
+#include
+
+#include "iostream-private.h"
+#include "context-private.h"
+
+dc_iostream_t *
+dc_iostream_allocate (dc_context_t *context, const dc_iostream_vtable_t *vtable)
+{
+ dc_iostream_t *iostream = NULL;
+
+ assert(vtable != NULL);
+ assert(vtable->size >= sizeof(dc_iostream_t));
+
+ // Allocate memory.
+ iostream = (dc_iostream_t *) malloc (vtable->size);
+ if (iostream == NULL) {
+ ERROR (context, "Failed to allocate memory.");
+ return iostream;
+ }
+
+ // Initialize the base class.
+ iostream->vtable = vtable;
+ iostream->context = context;
+
+ return iostream;
+}
+
+void
+dc_iostream_deallocate (dc_iostream_t *iostream)
+{
+ free (iostream);
+}
+
+int
+dc_iostream_isinstance (dc_iostream_t *iostream, const dc_iostream_vtable_t *vtable)
+{
+ if (iostream == NULL)
+ return 0;
+
+ return iostream->vtable == vtable;
+}
+
+dc_status_t
+dc_iostream_set_timeout (dc_iostream_t *iostream, int timeout)
+{
+ if (iostream == NULL || iostream->vtable->set_timeout == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ INFO (iostream->context, "Timeout: value=%i", timeout);
+
+ return iostream->vtable->set_timeout (iostream, timeout);
+}
+
+dc_status_t
+dc_iostream_set_latency (dc_iostream_t *iostream, unsigned int value)
+{
+ if (iostream == NULL || iostream->vtable->set_latency == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ INFO (iostream->context, "Latency: value=%i", value);
+
+ return iostream->vtable->set_latency (iostream, value);
+}
+
+dc_status_t
+dc_iostream_set_halfduplex (dc_iostream_t *iostream, unsigned int value)
+{
+ if (iostream == NULL || iostream->vtable->set_halfduplex == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ INFO (iostream->context, "Halfduplex: value=%i", value);
+
+ return iostream->vtable->set_halfduplex (iostream, value);
+}
+
+dc_status_t
+dc_iostream_set_break (dc_iostream_t *iostream, unsigned int value)
+{
+ if (iostream == NULL || iostream->vtable->set_break == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ INFO (iostream->context, "Break: value=%i", value);
+
+ return iostream->vtable->set_break (iostream, value);
+}
+
+dc_status_t
+dc_iostream_set_dtr (dc_iostream_t *iostream, unsigned int value)
+{
+ if (iostream == NULL || iostream->vtable->set_dtr == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ INFO (iostream->context, "DTR: value=%i", value);
+
+ return iostream->vtable->set_dtr (iostream, value);
+}
+
+dc_status_t
+dc_iostream_set_rts (dc_iostream_t *iostream, unsigned int value)
+{
+ if (iostream == NULL || iostream->vtable->set_rts == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ INFO (iostream->context, "RTS: value=%i", value);
+
+ return iostream->vtable->set_rts (iostream, value);
+}
+
+dc_status_t
+dc_iostream_get_lines (dc_iostream_t *iostream, unsigned int *value)
+{
+ if (iostream == NULL || iostream->vtable->get_lines == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ return iostream->vtable->get_lines (iostream, value);
+}
+
+dc_status_t
+dc_iostream_get_available (dc_iostream_t *iostream, size_t *value)
+{
+ if (iostream == NULL || iostream->vtable->get_available == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ return iostream->vtable->get_available (iostream, value);
+}
+
+dc_status_t
+dc_iostream_configure (dc_iostream_t *iostream, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol)
+{
+ if (iostream == NULL || iostream->vtable->configure == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ INFO (iostream->context, "Configure: baudrate=%i, databits=%i, parity=%i, stopbits=%i, flowcontrol=%i",
+ baudrate, databits, parity, stopbits, flowcontrol);
+
+ return iostream->vtable->configure (iostream, baudrate, databits, parity, stopbits, flowcontrol);
+}
+
+dc_status_t
+dc_iostream_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual)
+{
+ dc_status_t status = DC_STATUS_SUCCESS;
+ size_t nbytes = 0;
+
+ if (iostream == NULL || iostream->vtable->read == NULL) {
+ status = DC_STATUS_UNSUPPORTED;
+ goto out;
+ }
+
+ status = iostream->vtable->read (iostream, data, size, &nbytes);
+
+ HEXDUMP (iostream->context, DC_LOGLEVEL_INFO, "Read", (unsigned char *) data, nbytes);
+
+out:
+ if (actual)
+ *actual = nbytes;
+
+ return status;
+}
+
+dc_status_t
+dc_iostream_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual)
+{
+ dc_status_t status = DC_STATUS_SUCCESS;
+ size_t nbytes = 0;
+
+ if (iostream == NULL || iostream->vtable->read == NULL) {
+ status = DC_STATUS_UNSUPPORTED;
+ goto out;
+ }
+
+ status = iostream->vtable->write (iostream, data, size, &nbytes);
+
+ HEXDUMP (iostream->context, DC_LOGLEVEL_INFO, "Write", (const unsigned char *) data, nbytes);
+
+out:
+ if (actual)
+ *actual = nbytes;
+
+ return status;
+}
+
+dc_status_t
+dc_iostream_flush (dc_iostream_t *iostream)
+{
+ if (iostream == NULL || iostream->vtable->flush == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ INFO (iostream->context, "Flush: none");
+
+ return iostream->vtable->flush (iostream);
+}
+
+dc_status_t
+dc_iostream_purge (dc_iostream_t *iostream, dc_direction_t direction)
+{
+ if (iostream == NULL || iostream->vtable->purge == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ INFO (iostream->context, "Purge: direction=%u", direction);
+
+ return iostream->vtable->purge (iostream, direction);
+}
+
+dc_status_t
+dc_iostream_sleep (dc_iostream_t *iostream, unsigned int milliseconds)
+{
+ if (iostream == NULL || iostream->vtable->sleep == NULL)
+ return DC_STATUS_UNSUPPORTED;
+
+ INFO (iostream->context, "Sleep: value=%u", milliseconds);
+
+ return iostream->vtable->sleep (iostream, milliseconds);
+}
+
+dc_status_t
+dc_iostream_close (dc_iostream_t *iostream)
+{
+ dc_status_t status = DC_STATUS_SUCCESS;
+
+ if (iostream == NULL)
+ return DC_STATUS_SUCCESS;
+
+ if (iostream->vtable->close) {
+ status = iostream->vtable->close (iostream);
+ }
+
+ dc_iostream_deallocate (iostream);
+
+ return status;
+}
diff --git a/src/irda.c b/src/irda.c
index 1a2c38c..149808a 100644
--- a/src/irda.c
+++ b/src/irda.c
@@ -25,218 +25,89 @@
#include // malloc, free
#include // snprintf
+#include
+
+#include "socket.h"
+
#ifdef _WIN32
- #define NOGDI
- #include
- #include
- #ifdef HAVE_AF_IRDA_H
- #define IRDA
- #include
- #endif
+#ifdef HAVE_AF_IRDA_H
+#define IRDA
+#include
+#endif
#else
- #include // strerror
- #include // errno
- #include // close
- #include // socket, getsockopt
- #include // socket, getsockopt
- #ifdef HAVE_LINUX_IRDA_H
- #define IRDA
- #include // irda
- #include // irda
- #endif
- #include // select
- #include // ioctl
- #include
+#ifdef HAVE_LINUX_IRDA_H
+#define IRDA
+#include
+#include
+#endif
#endif
#include "irda.h"
+
#include "common-private.h"
#include "context-private.h"
+#include "iostream-private.h"
#include "array.h"
#include "platform.h"
-#ifdef _WIN32
-typedef int s_ssize_t;
-typedef DWORD s_errcode_t;
-#define S_ERRNO WSAGetLastError ()
-#define S_EINTR WSAEINTR
-#define S_EAGAIN WSAEWOULDBLOCK
-#define S_ENOMEM WSA_NOT_ENOUGH_MEMORY
-#define S_EINVAL WSAEINVAL
-#define S_EACCES WSAEACCES
-#define S_EAFNOSUPPORT WSAEAFNOSUPPORT
-#define S_INVALID INVALID_SOCKET
-#define S_IOCTL ioctlsocket
-#define S_CLOSE closesocket
-#else
-typedef ssize_t s_ssize_t;
-typedef int s_errcode_t;
-#define S_ERRNO errno
-#define S_EINTR EINTR
-#define S_EAGAIN EAGAIN
-#define S_ENOMEM ENOMEM
-#define S_EINVAL EINVAL
-#define S_EACCES EACCES
-#define S_EAFNOSUPPORT EAFNOSUPPORT
-#define S_INVALID -1
-#define S_IOCTL ioctl
-#define S_CLOSE close
-#endif
-
-struct dc_irda_t {
- dc_context_t *context;
-#ifdef _WIN32
- SOCKET fd;
-#else
- int fd;
-#endif
- int timeout;
-};
+#define ISINSTANCE(device) dc_iostream_isinstance((device), &dc_irda_vtable)
#ifdef IRDA
-static dc_status_t
-syserror(s_errcode_t errcode)
-{
- switch (errcode) {
- case S_EINVAL:
- return DC_STATUS_INVALIDARGS;
- case S_ENOMEM:
- return DC_STATUS_NOMEMORY;
- case S_EACCES:
- return DC_STATUS_NOACCESS;
- case S_EAFNOSUPPORT:
- return DC_STATUS_UNSUPPORTED;
- default:
- return DC_STATUS_IO;
- }
-}
+static const dc_iostream_vtable_t dc_irda_vtable = {
+ sizeof(dc_socket_t),
+ dc_socket_set_timeout, /* set_timeout */
+ dc_socket_set_latency, /* set_latency */
+ dc_socket_set_halfduplex, /* set_halfduplex */
+ dc_socket_set_break, /* set_break */
+ dc_socket_set_dtr, /* set_dtr */
+ dc_socket_set_rts, /* set_rts */
+ dc_socket_get_lines, /* get_lines */
+ dc_socket_get_available, /* get_received */
+ dc_socket_configure, /* configure */
+ dc_socket_read, /* read */
+ dc_socket_write, /* write */
+ dc_socket_flush, /* flush */
+ dc_socket_purge, /* purge */
+ dc_socket_sleep, /* sleep */
+ dc_socket_close, /* close */
+};
#endif
dc_status_t
-dc_irda_open (dc_irda_t **out, dc_context_t *context)
+dc_irda_open (dc_iostream_t **out, dc_context_t *context)
{
#ifdef IRDA
dc_status_t status = DC_STATUS_SUCCESS;
- dc_irda_t *device = NULL;
+ dc_socket_t *device = NULL;
if (out == NULL)
return DC_STATUS_INVALIDARGS;
// Allocate memory.
- device = (dc_irda_t *) malloc (sizeof (dc_irda_t));
+ device = (dc_socket_t *) dc_iostream_allocate (context, &dc_irda_vtable);
if (device == NULL) {
SYSERROR (context, S_ENOMEM);
return DC_STATUS_NOMEMORY;
}
- // Library context.
- device->context = context;
-
- // Default to blocking reads.
- device->timeout = -1;
-
-#ifdef _WIN32
- // Initialize the winsock dll.
- WSADATA wsaData;
- WORD wVersionRequested = MAKEWORD (2, 2);
- int rc = WSAStartup (wVersionRequested, &wsaData);
- if (rc != 0) {
- SYSERROR (context, rc);
- status = DC_STATUS_UNSUPPORTED;
+ // Open the socket.
+ status = dc_socket_open (&device->base, AF_IRDA, SOCK_STREAM, 0);
+ if (status != DC_STATUS_SUCCESS) {
goto error_free;
}
- // Confirm that the winsock dll supports version 2.2.
- // Note that if the dll supports versions greater than 2.2 in addition to
- // 2.2, it will still return 2.2 since that is the version we requested.
- if (LOBYTE (wsaData.wVersion) != 2 ||
- HIBYTE (wsaData.wVersion) != 2) {
- ERROR (context, "Incorrect winsock version.");
- status = DC_STATUS_UNSUPPORTED;
- goto error_wsacleanup;
- }
-#endif
-
- // Open the socket.
- device->fd = socket (AF_IRDA, SOCK_STREAM, 0);
- if (device->fd == S_INVALID) {
- s_errcode_t errcode = S_ERRNO;
- SYSERROR (context, errcode);
- status = syserror(errcode);
- goto error_wsacleanup;
- }
-
- *out = device;
+ *out = (dc_iostream_t *) device;
return DC_STATUS_SUCCESS;
-error_wsacleanup:
-#ifdef _WIN32
- WSACleanup ();
error_free:
-#endif
- free (device);
+ dc_iostream_deallocate ((dc_iostream_t *) device);
return status;
#else
return DC_STATUS_UNSUPPORTED;
#endif
}
-dc_status_t
-dc_irda_close (dc_irda_t *device)
-{
-#ifdef IRDA
- dc_status_t status = DC_STATUS_SUCCESS;
-
- if (device == NULL)
- return DC_STATUS_SUCCESS;
-
- // Terminate all send and receive operations.
- shutdown (device->fd, 0);
-
- // Close the socket.
- if (S_CLOSE (device->fd) != 0) {
- s_errcode_t errcode = S_ERRNO;
- SYSERROR (device->context, errcode);
- dc_status_set_error(&status, syserror(errcode));
- }
-
-#ifdef _WIN32
- // Terminate the winsock dll.
- if (WSACleanup () != 0) {
- s_errcode_t errcode = S_ERRNO;
- SYSERROR (device->context, errcode);
- dc_status_set_error(&status, syserror(errcode));
- }
-#endif
-
- // Free memory.
- free (device);
-
- return status;
-#else
- return DC_STATUS_UNSUPPORTED;
-#endif
-}
-
-dc_status_t
-dc_irda_set_timeout (dc_irda_t *device, int timeout)
-{
-#ifdef IRDA
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "Timeout: value=%i", timeout);
-
- device->timeout = timeout;
-
- return DC_STATUS_SUCCESS;
-#else
- return DC_STATUS_UNSUPPORTED;
-#endif
-}
-
-
#define DISCOVER_MAX_DEVICES 16 // Maximum number of devices.
#define DISCOVER_MAX_RETRIES 4 // Maximum number of retries.
@@ -249,10 +120,12 @@ dc_irda_set_timeout (dc_irda_t *device, int timeout)
#endif
dc_status_t
-dc_irda_discover (dc_irda_t *device, dc_irda_callback_t callback, void *userdata)
+dc_irda_discover (dc_iostream_t *abstract, dc_irda_callback_t callback, void *userdata)
{
#ifdef IRDA
- if (device == NULL)
+ dc_socket_t *device = (dc_socket_t *) abstract;
+
+ if (!ISINSTANCE (abstract))
return DC_STATUS_INVALIDARGS;
unsigned char data[DISCOVER_BUFSIZE] = {0};
@@ -280,8 +153,8 @@ dc_irda_discover (dc_irda_t *device, dc_irda_callback_t callback, void *userdata
if (rc != 0) {
s_errcode_t errcode = S_ERRNO;
if (errcode != S_EAGAIN) {
- SYSERROR (device->context, errcode);
- return syserror(errcode);
+ SYSERROR (abstract->context, errcode);
+ return dc_socket_syserror(errcode);
}
}
@@ -316,7 +189,7 @@ dc_irda_discover (dc_irda_t *device, dc_irda_callback_t callback, void *userdata
unsigned int hints = array_uint16_be (list->dev[i].hints);
#endif
- INFO (device->context,
+ INFO (abstract->context,
"Discover: address=%08x, name=%s, charset=%02x, hints=%04x",
address, name, charset, hints);
@@ -331,13 +204,15 @@ dc_irda_discover (dc_irda_t *device, dc_irda_callback_t callback, void *userdata
}
dc_status_t
-dc_irda_connect_name (dc_irda_t *device, unsigned int address, const char *name)
+dc_irda_connect_name (dc_iostream_t *abstract, unsigned int address, const char *name)
{
#ifdef IRDA
- if (device == NULL)
+ dc_socket_t *device = (dc_socket_t *) abstract;
+
+ if (!ISINSTANCE (abstract))
return DC_STATUS_INVALIDARGS;
- INFO (device->context, "Connect: address=%08x, name=%s", address, name ? name : "");
+ INFO (abstract->context, "Connect: address=%08x, name=%s", address, name ? name : "");
#ifdef _WIN32
SOCKADDR_IRDA peer;
@@ -360,26 +235,22 @@ dc_irda_connect_name (dc_irda_t *device, unsigned int address, const char *name)
memset (peer.sir_name, 0x00, 25);
#endif
- if (connect (device->fd, (struct sockaddr *) &peer, sizeof (peer)) != 0) {
- s_errcode_t errcode = S_ERRNO;
- SYSERROR (device->context, errcode);
- return syserror(errcode);
- }
-
- return DC_STATUS_SUCCESS;
+ return dc_socket_connect (&device->base, (struct sockaddr *) &peer, sizeof (peer));
#else
return DC_STATUS_UNSUPPORTED;
#endif
}
dc_status_t
-dc_irda_connect_lsap (dc_irda_t *device, unsigned int address, unsigned int lsap)
+dc_irda_connect_lsap (dc_iostream_t *abstract, unsigned int address, unsigned int lsap)
{
#ifdef IRDA
- if (device == NULL)
+ dc_socket_t *device = (dc_socket_t *) abstract;
+
+ if (!ISINSTANCE (abstract))
return DC_STATUS_INVALIDARGS;
- INFO (device->context, "Connect: address=%08x, lsap=%u", address, lsap);
+ INFO (abstract->context, "Connect: address=%08x, lsap=%u", address, lsap);
#ifdef _WIN32
SOCKADDR_IRDA peer;
@@ -397,171 +268,7 @@ dc_irda_connect_lsap (dc_irda_t *device, unsigned int address, unsigned int lsap
memset (peer.sir_name, 0x00, 25);
#endif
- if (connect (device->fd, (struct sockaddr *) &peer, sizeof (peer)) != 0) {
- s_errcode_t errcode = S_ERRNO;
- SYSERROR (device->context, errcode);
- return syserror(errcode);
- }
-
- return DC_STATUS_SUCCESS;
-#else
- return DC_STATUS_UNSUPPORTED;
-#endif
-}
-
-dc_status_t
-dc_irda_get_available (dc_irda_t *device, size_t *value)
-{
-#ifdef IRDA
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
-#ifdef _WIN32
- unsigned long bytes = 0;
-#else
- int bytes = 0;
-#endif
-
- if (S_IOCTL (device->fd, FIONREAD, &bytes) != 0) {
- s_errcode_t errcode = S_ERRNO;
- SYSERROR (device->context, errcode);
- return syserror(errcode);
- }
-
- if (value)
- *value = bytes;
-
- return DC_STATUS_SUCCESS;
-#else
- return DC_STATUS_UNSUPPORTED;
-#endif
-}
-
-dc_status_t
-dc_irda_read (dc_irda_t *device, void *data, size_t size, size_t *actual)
-{
-#ifdef IRDA
- dc_status_t status = DC_STATUS_SUCCESS;
- size_t nbytes = 0;
-
- if (device == NULL) {
- status = DC_STATUS_INVALIDARGS;
- goto out_invalidargs;
- }
-
- while (nbytes < size) {
- fd_set fds;
- FD_ZERO (&fds);
- FD_SET (device->fd, &fds);
-
- struct timeval tvt;
- if (device->timeout > 0) {
- tvt.tv_sec = (device->timeout / 1000);
- tvt.tv_usec = (device->timeout % 1000) * 1000;
- } else if (device->timeout == 0) {
- timerclear (&tvt);
- }
-
- int rc = select (device->fd + 1, &fds, NULL, NULL, device->timeout >= 0 ? &tvt : NULL);
- if (rc < 0) {
- s_errcode_t errcode = S_ERRNO;
- if (errcode == S_EINTR)
- continue; // Retry.
- SYSERROR (device->context, errcode);
- status = syserror(errcode);
- goto out;
- } else if (rc == 0) {
- break; // Timeout.
- }
-
- s_ssize_t n = recv (device->fd, (char*) data + nbytes, size - nbytes, 0);
- if (n < 0) {
- s_errcode_t errcode = S_ERRNO;
- if (errcode == S_EINTR || errcode == S_EAGAIN)
- continue; // Retry.
- SYSERROR (device->context, errcode);
- status = syserror(errcode);
- goto out;
- } else if (n == 0) {
- break; // EOF reached.
- }
-
- nbytes += n;
- }
-
- if (nbytes != size) {
- status = DC_STATUS_TIMEOUT;
- }
-
-out:
- HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Read", (unsigned char *) data, nbytes);
-
-out_invalidargs:
- if (actual)
- *actual = nbytes;
-
- return status;
-#else
- return DC_STATUS_UNSUPPORTED;
-#endif
-}
-
-dc_status_t
-dc_irda_write (dc_irda_t *device, const void *data, size_t size, size_t *actual)
-{
-#ifdef IRDA
- dc_status_t status = DC_STATUS_SUCCESS;
- size_t nbytes = 0;
-
- if (device == NULL) {
- status = DC_STATUS_INVALIDARGS;
- goto out_invalidargs;
- }
-
- while (nbytes < size) {
- fd_set fds;
- FD_ZERO (&fds);
- FD_SET (device->fd, &fds);
-
- int rc = select (device->fd + 1, NULL, &fds, NULL, NULL);
- if (rc < 0) {
- s_errcode_t errcode = S_ERRNO;
- if (errcode == S_EINTR)
- continue; // Retry.
- SYSERROR (device->context, errcode);
- status = syserror(errcode);
- goto out;
- } else if (rc == 0) {
- break; // Timeout.
- }
-
- s_ssize_t n = send (device->fd, (const char *) data + nbytes, size - nbytes, 0);
- if (n < 0) {
- s_errcode_t errcode = S_ERRNO;
- if (errcode == S_EINTR || errcode == S_EAGAIN)
- continue; // Retry.
- SYSERROR (device->context, errcode);
- status = syserror(errcode);
- goto out;
- } else if (n == 0) {
- break; // EOF.
- }
-
- nbytes += n;
- }
-
- if (nbytes != size) {
- status = DC_STATUS_TIMEOUT;
- }
-
-out:
- HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Write", (const unsigned char *) data, nbytes);
-
-out_invalidargs:
- if (actual)
- *actual = nbytes;
-
- return status;
+ return dc_socket_connect (&device->base, (struct sockaddr *) &peer, sizeof (peer));
#else
return DC_STATUS_UNSUPPORTED;
#endif
diff --git a/src/irda.h b/src/irda.h
index 84d2f4d..c413963 100644
--- a/src/irda.h
+++ b/src/irda.h
@@ -24,16 +24,12 @@
#include
#include
+#include
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-/**
- * Opaque object representing an IrDA connection.
- */
-typedef struct dc_irda_t dc_irda_t;
-
/**
* IrDA enumeration callback.
*
@@ -48,130 +44,49 @@ typedef void (*dc_irda_callback_t) (unsigned int address, const char *name, unsi
/**
* Open an IrDA connection.
*
- * @param[out] irda A location to store the IrDA connection.
+ * @param[out] iostream 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);
-
-/**
- * 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);
-
-/**
- * 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);
+dc_irda_open (dc_iostream_t **iostream, dc_context_t *context);
/**
* Enumerate the IrDA devices.
*
- * @param[in] irda A valid IrDA connection.
+ * @param[in] iostream 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);
+dc_irda_discover (dc_iostream_t *iostream, dc_irda_callback_t callback, void *userdata);
/**
* Connect to an IrDA device.
*
- * @param[in] irda A valid IrDA connection.
+ * @param[in] iostream 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);
+dc_irda_connect_name (dc_iostream_t *iostream, unsigned int address, const char *name);
/**
* Connect to an IrDA device.
*
- * @param[in] irda A valid IrDA connection.
+ * @param[in] iostream 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);
-
-/**
- * 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);
-
-/**
- * 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);
+dc_irda_connect_lsap (dc_iostream_t *iostream, unsigned int address, unsigned int lsap);
#ifdef __cplusplus
}
diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols
index 62f13c3..f272bd6 100644
--- a/src/libdivecomputer.symbols
+++ b/src/libdivecomputer.symbols
@@ -34,6 +34,22 @@ dc_descriptor_get_type
dc_descriptor_get_model
dc_descriptor_get_transport
+dc_iostream_set_timeout
+dc_iostream_set_halfduplex
+dc_iostream_set_latency
+dc_iostream_set_break
+dc_iostream_set_dtr
+dc_iostream_set_rts
+dc_iostream_get_available
+dc_iostream_get_lines
+dc_iostream_configure
+dc_iostream_read
+dc_iostream_write
+dc_iostream_flush
+dc_iostream_purge
+dc_iostream_sleep
+dc_iostream_close
+
dc_parser_new
dc_parser_new2
dc_parser_get_type
diff --git a/src/mares_common.c b/src/mares_common.c
index b157dc2..f476d8d 100644
--- a/src/mares_common.c
+++ b/src/mares_common.c
@@ -52,7 +52,7 @@ mares_common_device_init (mares_common_device_t *device)
assert (device != NULL);
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
device->echo = 0;
device->delay = 0;
}
@@ -88,11 +88,11 @@ mares_common_packet (mares_common_device_t *device, const unsigned char command[
return DC_STATUS_CANCELLED;
if (device->delay) {
- dc_serial_sleep (device->port, device->delay);
+ dc_iostream_sleep (device->iostream, device->delay);
}
// Send the command to the device.
- status = dc_serial_write (device->port, command, csize, NULL);
+ status = dc_iostream_write (device->iostream, command, csize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -101,7 +101,7 @@ mares_common_packet (mares_common_device_t *device, const unsigned char command[
if (device->echo) {
// Receive the echo of the command.
unsigned char echo[PACKETSIZE] = {0};
- status = dc_serial_read (device->port, echo, csize, NULL);
+ status = dc_iostream_read (device->iostream, echo, csize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the echo.");
return status;
@@ -114,7 +114,7 @@ mares_common_packet (mares_common_device_t *device, const unsigned char command[
}
// Receive the answer of the device.
- status = dc_serial_read (device->port, answer, asize, NULL);
+ status = dc_iostream_read (device->iostream, answer, asize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -155,8 +155,8 @@ mares_common_transfer (mares_common_device_t *device, const unsigned char comman
return rc;
// Discard any garbage bytes.
- dc_serial_sleep (device->port, 100);
- dc_serial_purge (device->port, DC_DIRECTION_INPUT);
+ dc_iostream_sleep (device->iostream, 100);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_INPUT);
}
return rc;
diff --git a/src/mares_common.h b/src/mares_common.h
index 4652d06..8cb58ca 100644
--- a/src/mares_common.h
+++ b/src/mares_common.h
@@ -41,7 +41,7 @@ typedef struct mares_common_layout_t {
typedef struct mares_common_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned int echo;
unsigned int delay;
} mares_common_device_t;
diff --git a/src/mares_darwin.c b/src/mares_darwin.c
index 4b1bc24..4f87f6f 100644
--- a/src/mares_darwin.c
+++ b/src/mares_darwin.c
@@ -125,43 +125,43 @@ mares_darwin_device_open (dc_device_t **out, dc_context_t *context, const char *
device->layout = &mares_darwin_layout;
// Open the device.
- status = dc_serial_open (&device->base.port, context, name);
+ status = dc_serial_open (&device->base.iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (9600 8N1).
- status = dc_serial_configure (device->base.port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->base.iostream, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (1000 ms).
- status = dc_serial_set_timeout (device->base.port, 1000);
+ status = dc_iostream_set_timeout (device->base.iostream, 1000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Set the DTR line.
- status = dc_serial_set_dtr (device->base.port, 1);
+ status = dc_iostream_set_dtr (device->base.iostream, 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);
+ status = dc_iostream_set_rts (device->base.iostream, 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.
- dc_serial_sleep (device->base.port, 100);
- dc_serial_purge (device->base.port, DC_DIRECTION_ALL);
+ dc_iostream_sleep (device->base.iostream, 100);
+ dc_iostream_purge (device->base.iostream, DC_DIRECTION_ALL);
// Override the base class values.
device->base.echo = 1;
@@ -172,7 +172,7 @@ mares_darwin_device_open (dc_device_t **out, dc_context_t *context, const char *
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->base.port);
+ dc_iostream_close (device->base.iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -186,7 +186,7 @@ mares_darwin_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->base.port);
+ rc = dc_iostream_close (device->base.iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
diff --git a/src/mares_iconhd.c b/src/mares_iconhd.c
index e945e9f..990f466 100644
--- a/src/mares_iconhd.c
+++ b/src/mares_iconhd.c
@@ -65,7 +65,7 @@ typedef struct mares_iconhd_model_t {
typedef struct mares_iconhd_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
const mares_iconhd_layout_t *layout;
unsigned char fingerprint[10];
unsigned char version[140];
@@ -157,7 +157,7 @@ mares_iconhd_transfer (mares_iconhd_device_t *device,
return DC_STATUS_CANCELLED;
// Send the command header to the dive computer.
- status = dc_serial_write (device->port, command, 2, NULL);
+ status = dc_iostream_write (device->iostream, command, 2, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -165,7 +165,7 @@ mares_iconhd_transfer (mares_iconhd_device_t *device,
// Receive the header byte.
unsigned char header[1] = {0};
- status = dc_serial_read (device->port, header, sizeof (header), NULL);
+ status = dc_iostream_read (device->iostream, header, sizeof (header), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -179,7 +179,7 @@ mares_iconhd_transfer (mares_iconhd_device_t *device,
// Send the command payload to the dive computer.
if (csize > 2) {
- status = dc_serial_write (device->port, command + 2, csize - 2, NULL);
+ status = dc_iostream_write (device->iostream, command + 2, csize - 2, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -187,7 +187,7 @@ mares_iconhd_transfer (mares_iconhd_device_t *device,
}
// Read the packet.
- status = dc_serial_read (device->port, answer, asize, NULL);
+ status = dc_iostream_read (device->iostream, answer, asize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -195,7 +195,7 @@ mares_iconhd_transfer (mares_iconhd_device_t *device,
// Receive the trailer byte.
unsigned char trailer[1] = {0};
- status = dc_serial_read (device->port, trailer, sizeof (trailer), NULL);
+ status = dc_iostream_read (device->iostream, trailer, sizeof (trailer), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -228,7 +228,7 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, const char *
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
device->layout = NULL;
memset (device->fingerprint, 0, sizeof (device->fingerprint));
memset (device->version, 0, sizeof (device->version));
@@ -236,42 +236,42 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, const char *
device->packetsize = 0;
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (115200 8E1).
- status = dc_serial_configure (device->port, 115200, 8, DC_PARITY_EVEN, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 115200, 8, DC_PARITY_EVEN, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (1000 ms).
- status = dc_serial_set_timeout (device->port, 1000);
+ status = dc_iostream_set_timeout (device->iostream, 1000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Clear the DTR line.
- status = dc_serial_set_dtr (device->port, 0);
+ status = dc_iostream_set_dtr (device->iostream, 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);
+ status = dc_iostream_set_rts (device->iostream, 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.
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
// Send the version command.
unsigned char command[] = {0xC2, 0x67};
@@ -315,7 +315,7 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, const char *
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -330,7 +330,7 @@ mares_iconhd_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
diff --git a/src/mares_nemo.c b/src/mares_nemo.c
index c73c24b..d6d4e01 100644
--- a/src/mares_nemo.c
+++ b/src/mares_nemo.c
@@ -45,7 +45,7 @@
typedef struct mares_nemo_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned char fingerprint[5];
} mares_nemo_device_t;
@@ -100,53 +100,53 @@ mares_nemo_device_open (dc_device_t **out, dc_context_t *context, const char *na
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
memset (device->fingerprint, 0, sizeof (device->fingerprint));
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (9600 8N1).
- status = dc_serial_configure (device->port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (1000 ms).
- status = dc_serial_set_timeout (device->port, 1000);
+ status = dc_iostream_set_timeout (device->iostream, 1000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Set the DTR line.
- status = dc_serial_set_dtr (device->port, 1);
+ status = dc_iostream_set_dtr (device->iostream, 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);
+ status = dc_iostream_set_rts (device->iostream, 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.
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
*out = (dc_device_t*) device;
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -161,7 +161,7 @@ mares_nemo_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -207,18 +207,18 @@ mares_nemo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
// Wait until some data arrives.
size_t available = 0;
- while (dc_serial_get_available (device->port, &available) == DC_STATUS_SUCCESS && available == 0) {
+ while (dc_iostream_get_available (device->iostream, &available) == DC_STATUS_SUCCESS && available == 0) {
if (device_is_cancelled (abstract))
return DC_STATUS_CANCELLED;
device_event_emit (abstract, DC_EVENT_WAITING, NULL);
- dc_serial_sleep (device->port, 100);
+ dc_iostream_sleep (device->iostream, 100);
}
// Receive the header of the package.
unsigned char header = 0x00;
for (unsigned int i = 0; i < 20;) {
- status = dc_serial_read (device->port, &header, 1, NULL);
+ status = dc_iostream_read (device->iostream, &header, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the header.");
return status;
@@ -238,7 +238,7 @@ 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};
- status = dc_serial_read (device->port, packet, sizeof (packet), NULL);
+ status = dc_iostream_read (device->iostream, packet, sizeof (packet), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
diff --git a/src/mares_puck.c b/src/mares_puck.c
index b220f54..5006b43 100644
--- a/src/mares_puck.c
+++ b/src/mares_puck.c
@@ -110,42 +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.
- status = dc_serial_open (&device->base.port, context, name);
+ status = dc_serial_open (&device->base.iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (38400 8N1).
- status = dc_serial_configure (device->base.port, 38400, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->base.iostream, 38400, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (1000 ms).
- status = dc_serial_set_timeout (device->base.port, 1000);
+ status = dc_iostream_set_timeout (device->base.iostream, 1000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Clear the DTR line.
- status = dc_serial_set_dtr (device->base.port, 0);
+ status = dc_iostream_set_dtr (device->base.iostream, 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);
+ status = dc_iostream_set_rts (device->base.iostream, 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.
- dc_serial_purge (device->base.port, DC_DIRECTION_ALL);
+ dc_iostream_purge (device->base.iostream, DC_DIRECTION_ALL);
// Identify the model number.
unsigned char header[PACKETSIZE] = {0};
@@ -176,7 +176,7 @@ mares_puck_device_open (dc_device_t **out, dc_context_t *context, const char *na
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->base.port);
+ dc_iostream_close (device->base.iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -191,7 +191,7 @@ mares_puck_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->base.port);
+ rc = dc_iostream_close (device->base.iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c
index bae6537..77c8e9d 100644
--- a/src/oceanic_atom2.c
+++ b/src/oceanic_atom2.c
@@ -54,7 +54,7 @@
typedef struct oceanic_atom2_device_t {
oceanic_common_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned int delay;
unsigned int bigpage;
unsigned char cache[256];
@@ -471,11 +471,11 @@ oceanic_atom2_packet (oceanic_atom2_device_t *device, const unsigned char comman
return DC_STATUS_CANCELLED;
if (device->delay) {
- dc_serial_sleep (device->port, device->delay);
+ dc_iostream_sleep (device->iostream, device->delay);
}
// Send the command to the dive computer.
- status = dc_serial_write (device->port, command, csize, NULL);
+ status = dc_iostream_write (device->iostream, command, csize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -489,7 +489,7 @@ 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;
- status = dc_serial_read (device->port, &response, 1, NULL);
+ status = dc_iostream_read (device->iostream, &response, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -503,7 +503,7 @@ oceanic_atom2_packet (oceanic_atom2_device_t *device, const unsigned char comman
if (asize) {
// Receive the answer of the dive computer.
- status = dc_serial_read (device->port, answer, asize, NULL);
+ status = dc_iostream_read (device->iostream, answer, asize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -552,8 +552,8 @@ oceanic_atom2_transfer (oceanic_atom2_device_t *device, const unsigned char comm
device->delay++;
// Delay the next attempt.
- dc_serial_sleep (device->port, 100);
- dc_serial_purge (device->port, DC_DIRECTION_INPUT);
+ dc_iostream_sleep (device->iostream, 100);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_INPUT);
}
return DC_STATUS_SUCCESS;
@@ -593,14 +593,14 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, const char
oceanic_common_device_init (&device->base);
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
device->delay = 0;
device->bigpage = 1; // no big pages
device->cached = INVALID;
memset(device->cache, 0, sizeof(device->cache));
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
@@ -613,28 +613,28 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, const char
}
// Set the serial communication protocol (38400 8N1).
- status = dc_serial_configure (device->port, baudrate, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, baudrate, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (1000 ms).
- status = dc_serial_set_timeout (device->port, 1000);
+ status = dc_iostream_set_timeout (device->iostream, 1000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Give the interface 100 ms to settle and draw power up.
- dc_serial_sleep (device->port, 100);
+ dc_iostream_sleep (device->iostream, 100);
// Set the DTR/RTS lines.
- dc_serial_set_dtr(device->port, 1);
- dc_serial_set_rts(device->port, 1);
+ dc_iostream_set_dtr(device->iostream, 1);
+ dc_iostream_set_rts(device->iostream, 1);
// Make sure everything is in a sane state.
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_purge (device->iostream, 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
@@ -712,7 +712,7 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, const char
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -733,7 +733,7 @@ oceanic_atom2_device_close (dc_device_t *abstract)
}
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
diff --git a/src/oceanic_veo250.c b/src/oceanic_veo250.c
index b6021dd..ffb1c05 100644
--- a/src/oceanic_veo250.c
+++ b/src/oceanic_veo250.c
@@ -40,7 +40,7 @@
typedef struct oceanic_veo250_device_t {
oceanic_common_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned int last;
} oceanic_veo250_device_t;
@@ -99,10 +99,10 @@ oceanic_veo250_send (oceanic_veo250_device_t *device, const unsigned char comman
return DC_STATUS_CANCELLED;
// Discard garbage bytes.
- dc_serial_purge (device->port, DC_DIRECTION_INPUT);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_INPUT);
// Send the command to the dive computer.
- status = dc_serial_write (device->port, command, csize, NULL);
+ status = dc_iostream_write (device->iostream, command, csize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -110,7 +110,7 @@ oceanic_veo250_send (oceanic_veo250_device_t *device, const unsigned char comman
// Receive the response (ACK/NAK) of the dive computer.
unsigned char response = NAK;
- status = dc_serial_read (device->port, &response, 1, NULL);
+ status = dc_iostream_read (device->iostream, &response, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -149,11 +149,11 @@ oceanic_veo250_transfer (oceanic_veo250_device_t *device, const unsigned char co
return rc;
// Delay the next attempt.
- dc_serial_sleep (device->port, 100);
+ dc_iostream_sleep (device->iostream, 100);
}
// Receive the answer of the dive computer.
- status = dc_serial_read (device->port, answer, asize, NULL);
+ status = dc_iostream_read (device->iostream, answer, asize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -177,7 +177,7 @@ oceanic_veo250_init (oceanic_veo250_device_t *device)
// Send the command to the dive computer.
unsigned char command[2] = {0x55, 0x00};
- status = dc_serial_write (device->port, command, sizeof (command), NULL);
+ status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -186,7 +186,7 @@ oceanic_veo250_init (oceanic_veo250_device_t *device)
// Receive the answer of the dive computer.
size_t n = 0;
unsigned char answer[13] = {0};
- status = dc_serial_read (device->port, answer, sizeof (answer), &n);
+ status = dc_iostream_read (device->iostream, answer, sizeof (answer), &n);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
if (n == 0)
@@ -215,7 +215,7 @@ oceanic_veo250_quit (oceanic_veo250_device_t *device)
// Send the command to the dive computer.
unsigned char command[2] = {0x98, 0x00};
- status = dc_serial_write (device->port, command, sizeof (command), NULL);
+ status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -248,49 +248,49 @@ oceanic_veo250_device_open (dc_device_t **out, dc_context_t *context, const char
device->base.multipage = MULTIPAGE;
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
device->last = 0;
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (9600 8N1).
- status = dc_serial_configure (device->port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (3000 ms).
- status = dc_serial_set_timeout (device->port, 3000);
+ status = dc_iostream_set_timeout (device->iostream, 3000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Set the DTR line.
- status = dc_serial_set_dtr (device->port, 1);
+ status = dc_iostream_set_dtr (device->iostream, 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);
+ status = dc_iostream_set_rts (device->iostream, 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.
- dc_serial_sleep (device->port, 100);
+ dc_iostream_sleep (device->iostream, 100);
// Make sure everything is in a sane state.
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
// Initialize the data cable (PPS mode).
status = oceanic_veo250_init (device);
@@ -299,7 +299,7 @@ oceanic_veo250_device_open (dc_device_t **out, dc_context_t *context, const char
}
// Delay the sending of the version command.
- dc_serial_sleep (device->port, 100);
+ dc_iostream_sleep (device->iostream, 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
@@ -322,7 +322,7 @@ oceanic_veo250_device_open (dc_device_t **out, dc_context_t *context, const char
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -343,7 +343,7 @@ oceanic_veo250_device_close (dc_device_t *abstract)
}
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
diff --git a/src/oceanic_vtpro.c b/src/oceanic_vtpro.c
index cc09892..e1ba31c 100644
--- a/src/oceanic_vtpro.c
+++ b/src/oceanic_vtpro.c
@@ -50,7 +50,7 @@ typedef enum oceanic_vtpro_protocol_t {
typedef struct oceanic_vtpro_device_t {
oceanic_common_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned int model;
oceanic_vtpro_protocol_t protocol;
} oceanic_vtpro_device_t;
@@ -140,7 +140,7 @@ oceanic_vtpro_send (oceanic_vtpro_device_t *device, const unsigned char command[
return DC_STATUS_CANCELLED;
// Send the command to the dive computer.
- status = dc_serial_write (device->port, command, csize, NULL);
+ status = dc_iostream_write (device->iostream, command, csize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -148,7 +148,7 @@ oceanic_vtpro_send (oceanic_vtpro_device_t *device, const unsigned char command[
// Receive the response (ACK/NAK) of the dive computer.
unsigned char response = NAK;
- status = dc_serial_read (device->port, &response, 1, NULL);
+ status = dc_iostream_read (device->iostream, &response, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -189,7 +189,7 @@ oceanic_vtpro_transfer (oceanic_vtpro_device_t *device, const unsigned char comm
if (asize) {
// Receive the answer of the dive computer.
- status = dc_serial_read (device->port, answer, asize, NULL);
+ status = dc_iostream_read (device->iostream, answer, asize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -210,7 +210,7 @@ oceanic_vtpro_init (oceanic_vtpro_device_t *device)
unsigned char command[2][2] = {
{0xAA, 0x00},
{0x20, 0x00}};
- status = dc_serial_write (device->port, command[device->protocol], sizeof (command[device->protocol]), NULL);
+ status = dc_iostream_write (device->iostream, command[device->protocol], sizeof (command[device->protocol]), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -218,7 +218,7 @@ oceanic_vtpro_init (oceanic_vtpro_device_t *device)
// Receive the answer of the dive computer.
unsigned char answer[13] = {0};
- status = dc_serial_read (device->port, answer, sizeof (answer), NULL);
+ status = dc_iostream_read (device->iostream, answer, sizeof (answer), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -269,9 +269,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};
- dc_serial_set_timeout (device->port, 9000);
+ dc_iostream_set_timeout (device->iostream, 9000);
dc_status_t rc = oceanic_vtpro_transfer (device, command, sizeof (command), answer, sizeof (answer));
- dc_serial_set_timeout (device->port, 3000);
+ dc_iostream_set_timeout (device->iostream, 3000);
if (rc != DC_STATUS_SUCCESS)
return rc;
@@ -337,7 +337,7 @@ oceanic_aeris500ai_device_logbook (dc_device_t *abstract, dc_event_progress_t *p
for (unsigned int i = 0; i < last + 1; ++i) {
// Receive the answer of the dive computer.
unsigned char answer[PAGESIZE / 2 + 1] = {0};
- rc = dc_serial_read (device->port, answer, sizeof(answer), NULL);
+ rc = dc_iostream_read (device->iostream, answer, sizeof(answer), NULL);
if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return rc;
@@ -407,7 +407,7 @@ oceanic_vtpro_device_open (dc_device_t **out, dc_context_t *context, const char
device->base.multipage = MULTIPAGE;
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
device->model = model;
if (model == AERIS500AI) {
device->protocol = INTR;
@@ -416,45 +416,45 @@ oceanic_vtpro_device_open (dc_device_t **out, dc_context_t *context, const char
}
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (9600 8N1).
- status = dc_serial_configure (device->port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (3000 ms).
- status = dc_serial_set_timeout (device->port, 3000);
+ status = dc_iostream_set_timeout (device->iostream, 3000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Set the DTR line.
- status = dc_serial_set_dtr (device->port, 1);
+ status = dc_iostream_set_dtr (device->iostream, 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);
+ status = dc_iostream_set_rts (device->iostream, 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.
- dc_serial_sleep (device->port, device->protocol == MOD ? 100 : 1000);
+ dc_iostream_sleep (device->iostream, device->protocol == MOD ? 100 : 1000);
// Make sure everything is in a sane state.
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
// Initialize the data cable (MOD mode).
status = oceanic_vtpro_init (device);
@@ -495,7 +495,7 @@ oceanic_vtpro_device_open (dc_device_t **out, dc_context_t *context, const char
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -516,7 +516,7 @@ oceanic_vtpro_device_close (dc_device_t *abstract)
}
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
diff --git a/src/reefnet_sensus.c b/src/reefnet_sensus.c
index 37c343a..0fc6e52 100644
--- a/src/reefnet_sensus.c
+++ b/src/reefnet_sensus.c
@@ -36,7 +36,7 @@
typedef struct reefnet_sensus_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned char handshake[SZ_HANDSHAKE];
unsigned int waiting;
unsigned int timestamp;
@@ -72,7 +72,7 @@ reefnet_sensus_cancel (reefnet_sensus_device_t *device)
// Send the command to the device.
unsigned char command = 0x00;
- status = dc_serial_write (device->port, &command, 1, NULL);
+ status = dc_iostream_write (device->iostream, &command, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -102,7 +102,7 @@ reefnet_sensus_device_open (dc_device_t **out, dc_context_t *context, const char
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
device->waiting = 0;
device->timestamp = 0;
device->systime = (dc_ticks_t) -1;
@@ -110,35 +110,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.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (19200 8N1).
- status = dc_serial_configure (device->port, 19200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 19200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (3000 ms).
- status = dc_serial_set_timeout (device->port, 3000);
+ status = dc_iostream_set_timeout (device->iostream, 3000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Make sure everything is in a sane state.
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
*out = (dc_device_t*) device;
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -162,7 +162,7 @@ reefnet_sensus_device_close (dc_device_t *abstract)
}
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -215,7 +215,7 @@ reefnet_sensus_handshake (reefnet_sensus_device_t *device)
// Send the command to the device.
unsigned char command = 0x0A;
- status = dc_serial_write (device->port, &command, 1, NULL);
+ status = dc_iostream_write (device->iostream, &command, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -223,7 +223,7 @@ reefnet_sensus_handshake (reefnet_sensus_device_t *device)
// Receive the answer from the device.
unsigned char handshake[SZ_HANDSHAKE + 2] = {0};
- status = dc_serial_read (device->port, handshake, sizeof (handshake), NULL);
+ status = dc_iostream_read (device->iostream, handshake, sizeof (handshake), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the handshake.");
return status;
@@ -267,7 +267,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.
- dc_serial_sleep (device->port, 10);
+ dc_iostream_sleep (device->iostream, 10);
return DC_STATUS_SUCCESS;
}
@@ -298,7 +298,7 @@ reefnet_sensus_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
// Send the command to the device.
unsigned char command = 0x40;
- status = dc_serial_write (device->port, &command, 1, NULL);
+ status = dc_iostream_write (device->iostream, &command, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -315,7 +315,7 @@ reefnet_sensus_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
if (len > 128)
len = 128;
- status = dc_serial_read (device->port, answer + nbytes, len, NULL);
+ status = dc_iostream_read (device->iostream, answer + nbytes, len, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
diff --git a/src/reefnet_sensuspro.c b/src/reefnet_sensuspro.c
index 4df3c07..e50cb44 100644
--- a/src/reefnet_sensuspro.c
+++ b/src/reefnet_sensuspro.c
@@ -36,7 +36,7 @@
typedef struct reefnet_sensuspro_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned char handshake[SZ_HANDSHAKE];
unsigned int timestamp;
unsigned int devtime;
@@ -80,42 +80,42 @@ reefnet_sensuspro_device_open (dc_device_t **out, dc_context_t *context, const c
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
device->timestamp = 0;
device->systime = (dc_ticks_t) -1;
device->devtime = 0;
memset (device->handshake, 0, sizeof (device->handshake));
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (19200 8N1).
- status = dc_serial_configure (device->port, 19200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 19200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (3000ms).
- status = dc_serial_set_timeout (device->port, 3000);
+ status = dc_iostream_set_timeout (device->iostream, 3000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Make sure everything is in a sane state.
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
*out = (dc_device_t*) device;
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -130,7 +130,7 @@ reefnet_sensuspro_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -182,18 +182,18 @@ reefnet_sensuspro_handshake (reefnet_sensuspro_device_t *device)
dc_device_t *abstract = (dc_device_t *) device;
// Assert a break condition.
- dc_serial_set_break (device->port, 1);
+ dc_iostream_set_break (device->iostream, 1);
// Receive the handshake from the dive computer.
unsigned char handshake[SZ_HANDSHAKE + 2] = {0};
- status = dc_serial_read (device->port, handshake, sizeof (handshake), NULL);
+ status = dc_iostream_read (device->iostream, handshake, sizeof (handshake), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the handshake.");
return status;
}
// Clear the break condition again.
- dc_serial_set_break (device->port, 0);
+ dc_iostream_set_break (device->iostream, 0);
// Verify the checksum of the handshake packet.
unsigned short crc = array_uint16_le (handshake + SZ_HANDSHAKE);
@@ -229,7 +229,7 @@ reefnet_sensuspro_handshake (reefnet_sensuspro_device_t *device)
vendor.size = sizeof (device->handshake);
device_event_emit (abstract, DC_EVENT_VENDOR, &vendor);
- dc_serial_sleep (device->port, 10);
+ dc_iostream_sleep (device->iostream, 10);
return DC_STATUS_SUCCESS;
}
@@ -247,7 +247,7 @@ reefnet_sensuspro_send (reefnet_sensuspro_device_t *device, unsigned char comman
return rc;
// Send the instruction code to the device.
- status = dc_serial_write (device->port, &command, 1, NULL);
+ status = dc_iostream_write (device->iostream, &command, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -287,7 +287,7 @@ reefnet_sensuspro_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
if (len > 256)
len = 256;
- status = dc_serial_read (device->port, answer + nbytes, len, NULL);
+ status = dc_iostream_read (device->iostream, answer + nbytes, len, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -352,9 +352,9 @@ reefnet_sensuspro_device_write_interval (dc_device_t *abstract, unsigned char in
if (rc != DC_STATUS_SUCCESS)
return rc;
- dc_serial_sleep (device->port, 10);
+ dc_iostream_sleep (device->iostream, 10);
- status = dc_serial_write (device->port, &interval, 1, NULL);
+ status = dc_iostream_write (device->iostream, &interval, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the data packet.");
return status;
diff --git a/src/reefnet_sensusultra.c b/src/reefnet_sensusultra.c
index fba7511..fd3d399 100644
--- a/src/reefnet_sensusultra.c
+++ b/src/reefnet_sensusultra.c
@@ -45,7 +45,7 @@
typedef struct reefnet_sensusultra_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned char handshake[SZ_HANDSHAKE];
unsigned int timestamp;
unsigned int devtime;
@@ -87,42 +87,42 @@ reefnet_sensusultra_device_open (dc_device_t **out, dc_context_t *context, const
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
device->timestamp = 0;
device->systime = (dc_ticks_t) -1;
device->devtime = 0;
memset (device->handshake, 0, sizeof (device->handshake));
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (115200 8N1).
- status = dc_serial_configure (device->port, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (3000ms).
- status = dc_serial_set_timeout (device->port, 3000);
+ status = dc_iostream_set_timeout (device->iostream, 3000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Make sure everything is in a sane state.
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
*out = (dc_device_t*) device;
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -137,7 +137,7 @@ reefnet_sensusultra_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -190,7 +190,7 @@ reefnet_sensusultra_send_uchar (reefnet_sensusultra_device_t *device, unsigned c
// Wait for the prompt byte.
unsigned char prompt = 0;
- status = dc_serial_read (device->port, &prompt, 1, NULL);
+ status = dc_iostream_read (device->iostream, &prompt, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the prompt byte");
return status;
@@ -203,7 +203,7 @@ reefnet_sensusultra_send_uchar (reefnet_sensusultra_device_t *device, unsigned c
}
// Send the value to the device.
- status = dc_serial_write (device->port, &value, 1, NULL);
+ status = dc_iostream_write (device->iostream, &value, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the value.");
return status;
@@ -244,7 +244,7 @@ reefnet_sensusultra_packet (reefnet_sensusultra_device_t *device, unsigned char
return DC_STATUS_CANCELLED;
// Receive the data packet.
- status = dc_serial_read (device->port, data, size, NULL);
+ status = dc_iostream_read (device->iostream, data, size, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the packet.");
return status;
@@ -346,7 +346,7 @@ static dc_status_t
reefnet_sensusultra_send (reefnet_sensusultra_device_t *device, unsigned short command)
{
// Flush the input and output buffers.
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
// Wake-up the device and send the instruction code.
unsigned int nretries = 0;
@@ -366,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.
- dc_serial_sleep (device->port, 250);
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_sleep (device->iostream, 250);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
}
return DC_STATUS_SUCCESS;
diff --git a/src/scubapro_g2.c b/src/scubapro_g2.c
index a01619c..dcef627 100644
--- a/src/scubapro_g2.c
+++ b/src/scubapro_g2.c
@@ -383,7 +383,7 @@ scubapro_g2_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
progress.current += 4;
device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress);
- if (length == 0)
+ if (length == 0)
return DC_STATUS_SUCCESS;
// Allocate the required amount of memory.
diff --git a/src/serial.h b/src/serial.h
index 10da402..d6620e0 100644
--- a/src/serial.h
+++ b/src/serial.h
@@ -24,67 +24,12 @@
#include
#include
+#include
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-/**
- * Opaque object representing a serial connection.
- */
-typedef struct dc_serial_t dc_serial_t;
-
-#ifndef __SERIAL_TYPES__
-#define __SERIAL_TYPES__
-/**
- * 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;
-
-/**
- * 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;
-
-/**
- * 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;
-
-/**
- * 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;
-
-/**
- * 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;
-#endif /* __SERIAL_TYPES__ */
-
/**
* Serial enumeration callback.
*
@@ -107,216 +52,14 @@ dc_serial_enumerate (dc_serial_callback_t callback, void *userdata);
/**
* Open a serial connection.
*
- * @param[out] serial A location to store the serial connection.
+ * @param[out] iostream 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);
-
-/**
- * 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);
-
-/**
- * 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);
-
-/**
- * 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);
-
-/**
- * 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);
-
-/**
- * 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);
-
-/**
- * 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);
-
-/**
- * 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);
-
-/**
- * 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);
-
-/**
- * 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);
-
-/**
- * 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);
-
-/**
- * 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);
-
-/**
- * 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);
-
-/**
- * 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);
+dc_serial_open (dc_iostream_t **iostream, dc_context_t *context, const char *name);
#ifdef __cplusplus
}
diff --git a/src/serial_posix.c b/src/serial_posix.c
index 7f07206..1698df8 100644
--- a/src/serial_posix.c
+++ b/src/serial_posix.c
@@ -54,12 +54,29 @@
#endif
#include "serial.h"
+
#include "common-private.h"
#include "context-private.h"
+#include "iostream-private.h"
-struct dc_serial_t {
- /* Library context. */
- dc_context_t *context;
+static dc_status_t dc_serial_set_timeout (dc_iostream_t *iostream, int timeout);
+static dc_status_t dc_serial_set_latency (dc_iostream_t *iostream, unsigned int value);
+static dc_status_t dc_serial_set_halfduplex (dc_iostream_t *iostream, unsigned int value);
+static dc_status_t dc_serial_set_break (dc_iostream_t *iostream, unsigned int value);
+static dc_status_t dc_serial_set_dtr (dc_iostream_t *iostream, unsigned int value);
+static dc_status_t dc_serial_set_rts (dc_iostream_t *iostream, unsigned int value);
+static dc_status_t dc_serial_get_lines (dc_iostream_t *iostream, unsigned int *value);
+static dc_status_t dc_serial_get_available (dc_iostream_t *iostream, size_t *value);
+static dc_status_t dc_serial_configure (dc_iostream_t *iostream, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
+static dc_status_t dc_serial_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
+static dc_status_t dc_serial_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
+static dc_status_t dc_serial_flush (dc_iostream_t *iostream);
+static dc_status_t dc_serial_purge (dc_iostream_t *iostream, dc_direction_t direction);
+static dc_status_t dc_serial_sleep (dc_iostream_t *iostream, unsigned int milliseconds);
+static dc_status_t dc_serial_close (dc_iostream_t *iostream);
+
+typedef struct dc_serial_t {
+ dc_iostream_t base;
/*
* The file descriptor corresponding to the serial port.
*/
@@ -75,6 +92,25 @@ struct dc_serial_t {
int halfduplex;
unsigned int baudrate;
unsigned int nbits;
+} dc_serial_t;
+
+static const dc_iostream_vtable_t dc_serial_vtable = {
+ sizeof(dc_serial_t),
+ dc_serial_set_timeout, /* set_timeout */
+ dc_serial_set_latency, /* set_latency */
+ dc_serial_set_halfduplex, /* set_halfduplex */
+ dc_serial_set_break, /* set_break */
+ dc_serial_set_dtr, /* set_dtr */
+ dc_serial_set_rts, /* set_rts */
+ dc_serial_get_lines, /* get_lines */
+ dc_serial_get_available, /* get_received */
+ dc_serial_configure, /* configure */
+ dc_serial_read, /* read */
+ dc_serial_write, /* write */
+ dc_serial_flush, /* flush */
+ dc_serial_purge, /* purge */
+ dc_serial_sleep, /* sleep */
+ dc_serial_close, /* close */
};
static dc_status_t
@@ -140,25 +176,27 @@ dc_serial_enumerate (dc_serial_callback_t callback, void *userdata)
}
dc_status_t
-dc_serial_open (dc_serial_t **out, dc_context_t *context, const char *name)
+dc_serial_open (dc_iostream_t **out, dc_context_t *context, const char *name)
{
dc_status_t status = DC_STATUS_SUCCESS;
+ dc_serial_t *device = NULL;
- if (out == NULL)
+ if (out == NULL || name == NULL)
return DC_STATUS_INVALIDARGS;
- INFO (context, "Open: name=%s", name ? name : "");
+ // Are we using custom IO?
+ if (_dc_context_custom_io(context))
+ return dc_custom_io_serial_open(out, context, name);
+
+ INFO (context, "Open: name=%s", name);
// Allocate memory.
- dc_serial_t *device = (dc_serial_t *) malloc (sizeof (dc_serial_t));
+ device = (dc_serial_t *) dc_iostream_allocate (context, &dc_serial_vtable);
if (device == NULL) {
SYSERROR (context, ENOMEM);
return DC_STATUS_NOMEMORY;
}
- // Library context.
- device->context = context;
-
// Default to blocking reads.
device->timeout = -1;
@@ -167,8 +205,6 @@ dc_serial_open (dc_serial_t **out, dc_context_t *context, const char *name)
device->baudrate = 0;
device->nbits = 0;
- RETURN_IF_CUSTOM_SERIAL(context, *out = device, open, context, name);
-
// Open the device in non-blocking mode, to return immediately
// without waiting for the modem connection to complete.
device->fd = open (name, O_RDWR | O_NOCTTY | O_NONBLOCK);
@@ -200,31 +236,27 @@ dc_serial_open (dc_serial_t **out, dc_context_t *context, const char *name)
goto error_close;
}
- *out = device;
+ *out = (dc_iostream_t *) device;
return DC_STATUS_SUCCESS;
error_close:
close (device->fd);
error_free:
- free (device);
+ dc_iostream_deallocate ((dc_iostream_t *) device);
return status;
}
-dc_status_t
-dc_serial_close (dc_serial_t *device)
+static dc_status_t
+dc_serial_close (dc_iostream_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
-
- if (device == NULL)
- return DC_STATUS_SUCCESS;
-
- RETURN_IF_CUSTOM_SERIAL(device->context, free(device), close);
+ dc_serial_t *device = (dc_serial_t *) abstract;
// Restore the initial terminal attributes.
if (tcsetattr (device->fd, TCSANOW, &device->tty) != 0) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
dc_status_set_error(&status, syserror (errcode));
}
@@ -236,33 +268,24 @@ dc_serial_close (dc_serial_t *device)
// Close the device.
if (close (device->fd) != 0) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
dc_status_set_error(&status, syserror (errcode));
}
- // Free memory.
- free (device);
-
return status;
}
-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)
+static dc_status_t
+dc_serial_configure (dc_iostream_t *abstract, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "Configure: baudrate=%i, databits=%i, parity=%i, stopbits=%i, flowcontrol=%i",
- baudrate, databits, parity, stopbits, flowcontrol);
-
- RETURN_IF_CUSTOM_SERIAL(device->context, , configure, baudrate, databits, parity, stopbits, flowcontrol);
+ dc_serial_t *device = (dc_serial_t *) abstract;
// Retrieve the current settings.
struct termios tty;
memset (&tty, 0, sizeof (tty));
if (tcgetattr (device->fd, &tty) != 0) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
@@ -359,7 +382,7 @@ dc_serial_configure (dc_serial_t *device, unsigned int baudrate, unsigned int da
if (cfsetispeed (&tty, baud) != 0 ||
cfsetospeed (&tty, baud) != 0) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
@@ -455,11 +478,9 @@ dc_serial_configure (dc_serial_t *device, unsigned int baudrate, unsigned int da
// Apply the new settings.
if (tcsetattr (device->fd, TCSANOW, &tty) != 0 && NOPTY) {
-#if 0 // who cares
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
-#endif
}
// Configure a custom baudrate if necessary.
@@ -469,7 +490,7 @@ dc_serial_configure (dc_serial_t *device, unsigned int baudrate, unsigned int da
struct serial_struct ss;
if (ioctl (device->fd, TIOCGSERIAL, &ss) != 0 && NOPTY) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
@@ -481,14 +502,14 @@ dc_serial_configure (dc_serial_t *device, unsigned int baudrate, unsigned int da
// Apply the new settings.
if (ioctl (device->fd, TIOCSSERIAL, &ss) != 0 && NOPTY) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
#elif defined(IOSSIOSPEED)
speed_t speed = baudrate;
if (ioctl (device->fd, IOSSIOSPEED, &speed) != 0 && NOPTY) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
#else
@@ -503,46 +524,37 @@ dc_serial_configure (dc_serial_t *device, unsigned int baudrate, unsigned int da
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_set_timeout (dc_serial_t *device, int timeout)
+static dc_status_t
+dc_serial_set_timeout (dc_iostream_t *abstract, int timeout)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "Timeout: value=%i", timeout);
-
- RETURN_IF_CUSTOM_SERIAL(device->context, , set_timeout, timeout);
+ dc_serial_t *device = (dc_serial_t *) abstract;
device->timeout = timeout;
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_set_halfduplex (dc_serial_t *device, unsigned int value)
+static dc_status_t
+dc_serial_set_halfduplex (dc_iostream_t *abstract, unsigned int value)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- RETURN_IF_CUSTOM_SERIAL(device->context, , set_halfduplex, value);
+ dc_serial_t *device = (dc_serial_t *) abstract;
device->halfduplex = value;
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_set_latency (dc_serial_t *device, unsigned int milliseconds)
+static dc_status_t
+dc_serial_set_latency (dc_iostream_t *abstract, unsigned int milliseconds)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
+ dc_serial_t *device = (dc_serial_t *) abstract;
#if defined(TIOCGSERIAL) && defined(TIOCSSERIAL) && !defined(__ANDROID__)
// Get the current settings.
struct serial_struct ss;
if (ioctl (device->fd, TIOCGSERIAL, &ss) != 0 && NOPTY) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
@@ -556,7 +568,7 @@ dc_serial_set_latency (dc_serial_t *device, unsigned int milliseconds)
// Apply the new settings.
if (ioctl (device->fd, TIOCSSERIAL, &ss) != 0 && NOPTY) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
#elif defined(IOSSDATALAT)
@@ -566,7 +578,7 @@ dc_serial_set_latency (dc_serial_t *device, unsigned int milliseconds)
unsigned long usec = (milliseconds == 0 ? 1 : milliseconds * 1000);
if (ioctl (device->fd, IOSSDATALAT, &usec) != 0 && NOPTY) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
#endif
@@ -574,25 +586,13 @@ dc_serial_set_latency (dc_serial_t *device, unsigned int milliseconds)
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_read (dc_serial_t *device, void *data, size_t size, size_t *actual)
+static dc_status_t
+dc_serial_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
{
dc_status_t status = DC_STATUS_SUCCESS;
+ dc_serial_t *device = (dc_serial_t *) abstract;
size_t nbytes = 0;
- if (device == NULL) {
- status = DC_STATUS_INVALIDARGS;
- goto out_invalidargs;
- }
-
- RETURN_IF_CUSTOM_SERIAL(device->context,
- {
- HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Custom Read", (unsigned char *) data, nbytes);
- if (actual)
- *actual = nbytes;
- },
- read, data, size, &nbytes);
-
// The total timeout.
int timeout = device->timeout;
@@ -610,7 +610,7 @@ dc_serial_read (dc_serial_t *device, void *data, size_t size, size_t *actual)
struct timeval now;
if (gettimeofday (&now, NULL) != 0) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
status = syserror (errcode);
goto out;
}
@@ -638,7 +638,7 @@ dc_serial_read (dc_serial_t *device, void *data, size_t size, size_t *actual)
int errcode = errno;
if (errcode == EINTR)
continue; // Retry.
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
status = syserror (errcode);
goto out;
} else if (rc == 0) {
@@ -650,7 +650,7 @@ dc_serial_read (dc_serial_t *device, void *data, size_t size, size_t *actual)
int errcode = errno;
if (errcode == EINTR || errcode == EAGAIN)
continue; // Retry.
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
status = syserror (errcode);
goto out;
} else if (n == 0) {
@@ -665,40 +665,25 @@ dc_serial_read (dc_serial_t *device, void *data, size_t size, size_t *actual)
}
out:
- HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Read", (unsigned char *) data, nbytes);
-
-out_invalidargs:
if (actual)
*actual = nbytes;
return status;
}
-dc_status_t
-dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *actual)
+static dc_status_t
+dc_serial_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual)
{
dc_status_t status = DC_STATUS_SUCCESS;
+ dc_serial_t *device = (dc_serial_t *) abstract;
size_t nbytes = 0;
- if (device == NULL) {
- status = DC_STATUS_INVALIDARGS;
- goto out_invalidargs;
- }
-
- RETURN_IF_CUSTOM_SERIAL(device->context,
- {
- HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Custom Write", (unsigned char *) data, nbytes);
- if (actual)
- *actual = nbytes;
- },
- write, data, size, &nbytes);
-
struct timeval tve, tvb;
if (device->halfduplex) {
// Get the current time.
if (gettimeofday (&tvb, NULL) != 0) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
status = syserror (errcode);
goto out;
}
@@ -714,7 +699,7 @@ dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *act
int errcode = errno;
if (errcode == EINTR)
continue; // Retry.
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
status = syserror (errcode);
goto out;
} else if (rc == 0) {
@@ -726,7 +711,7 @@ dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *act
int errcode = errno;
if (errcode == EINTR || errcode == EAGAIN)
continue; // Retry.
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
status = syserror (errcode);
goto out;
} else if (n == 0) {
@@ -745,7 +730,7 @@ dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *act
#endif
int errcode = errno;
if (errcode != EINTR ) {
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
status = syserror (errcode);
goto out;
}
@@ -755,7 +740,7 @@ dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *act
// Get the current time.
if (gettimeofday (&tve, NULL) != 0) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
status = syserror (errcode);
goto out;
}
@@ -776,29 +761,21 @@ dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *act
// 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.
- dc_serial_sleep (device, (remaining + 999) / 1000);
+ dc_serial_sleep (abstract, (remaining + 999) / 1000);
}
}
out:
- HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Write", (const unsigned char *) data, nbytes);
-
-out_invalidargs:
if (actual)
*actual = nbytes;
return status;
}
-dc_status_t
-dc_serial_purge (dc_serial_t *device, dc_direction_t direction)
+static dc_status_t
+dc_serial_purge (dc_iostream_t *abstract, dc_direction_t direction)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "Purge: direction=%u", direction);
-
- RETURN_IF_CUSTOM_SERIAL(device->context, , purge, direction);
+ dc_serial_t *device = (dc_serial_t *) abstract;
int flags = 0;
@@ -818,101 +795,78 @@ dc_serial_purge (dc_serial_t *device, dc_direction_t direction)
if (tcflush (device->fd, flags) != 0) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_flush (dc_serial_t *device)
+static dc_status_t
+dc_serial_flush (dc_iostream_t *abstract)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "Flush: none");
-
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_set_break (dc_serial_t *device, unsigned int level)
+static dc_status_t
+dc_serial_set_break (dc_iostream_t *abstract, unsigned int level)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "Break: value=%i", level);
-
- RETURN_IF_CUSTOM_SERIAL(device->context, , set_break, level);
+ dc_serial_t *device = (dc_serial_t *) abstract;
unsigned long action = (level ? TIOCSBRK : TIOCCBRK);
if (ioctl (device->fd, action, NULL) != 0 && NOPTY) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_set_dtr (dc_serial_t *device, unsigned int level)
+static dc_status_t
+dc_serial_set_dtr (dc_iostream_t *abstract, unsigned int level)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "DTR: value=%i", level);
-
- RETURN_IF_CUSTOM_SERIAL(device->context, , set_dtr, level);
+ dc_serial_t *device = (dc_serial_t *) abstract;
unsigned long action = (level ? TIOCMBIS : TIOCMBIC);
int value = TIOCM_DTR;
if (ioctl (device->fd, action, &value) != 0 && NOPTY) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_set_rts (dc_serial_t *device, unsigned int level)
+static dc_status_t
+dc_serial_set_rts (dc_iostream_t *abstract, unsigned int level)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "RTS: value=%i", level);
-
- RETURN_IF_CUSTOM_SERIAL(device->context, , set_rts, level);
+ dc_serial_t *device = (dc_serial_t *) abstract;
unsigned long action = (level ? TIOCMBIS : TIOCMBIC);
int value = TIOCM_RTS;
if (ioctl (device->fd, action, &value) != 0 && NOPTY) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_get_available (dc_serial_t *device, size_t *value)
+static dc_status_t
+dc_serial_get_available (dc_iostream_t *abstract, size_t *value)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- RETURN_IF_CUSTOM_SERIAL(device->context, , get_available, value);
+ dc_serial_t *device = (dc_serial_t *) abstract;
int bytes = 0;
if (ioctl (device->fd, TIOCINQ, &bytes) != 0) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
@@ -922,18 +876,16 @@ dc_serial_get_available (dc_serial_t *device, size_t *value)
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_get_lines (dc_serial_t *device, unsigned int *value)
+static dc_status_t
+dc_serial_get_lines (dc_iostream_t *abstract, unsigned int *value)
{
+ dc_serial_t *device = (dc_serial_t *) abstract;
unsigned int lines = 0;
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
int status = 0;
if (ioctl (device->fd, TIOCMGET, &status) != 0) {
int errcode = errno;
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
@@ -952,14 +904,9 @@ dc_serial_get_lines (dc_serial_t *device, unsigned int *value)
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_sleep (dc_serial_t *device, unsigned int timeout)
+static dc_status_t
+dc_serial_sleep (dc_iostream_t *abstract, unsigned int timeout)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "Sleep: value=%u", timeout);
-
struct timespec ts;
ts.tv_sec = (timeout / 1000);
ts.tv_nsec = (timeout % 1000) * 1000000;
@@ -967,7 +914,7 @@ dc_serial_sleep (dc_serial_t *device, unsigned int timeout)
while (nanosleep (&ts, &ts) != 0) {
int errcode = errno;
if (errcode != EINTR ) {
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
}
diff --git a/src/serial_win32.c b/src/serial_win32.c
index 540ec11..b530c9b 100644
--- a/src/serial_win32.c
+++ b/src/serial_win32.c
@@ -25,12 +25,29 @@
#include
#include "serial.h"
+
#include "common-private.h"
#include "context-private.h"
+#include "iostream-private.h"
-struct dc_serial_t {
- /* Library context. */
- dc_context_t *context;
+static dc_status_t dc_serial_set_timeout (dc_iostream_t *iostream, int timeout);
+static dc_status_t dc_serial_set_latency (dc_iostream_t *iostream, unsigned int value);
+static dc_status_t dc_serial_set_halfduplex (dc_iostream_t *iostream, unsigned int value);
+static dc_status_t dc_serial_set_break (dc_iostream_t *iostream, unsigned int value);
+static dc_status_t dc_serial_set_dtr (dc_iostream_t *iostream, unsigned int value);
+static dc_status_t dc_serial_set_rts (dc_iostream_t *iostream, unsigned int value);
+static dc_status_t dc_serial_get_lines (dc_iostream_t *iostream, unsigned int *value);
+static dc_status_t dc_serial_get_available (dc_iostream_t *iostream, size_t *value);
+static dc_status_t dc_serial_configure (dc_iostream_t *iostream, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
+static dc_status_t dc_serial_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
+static dc_status_t dc_serial_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
+static dc_status_t dc_serial_flush (dc_iostream_t *iostream);
+static dc_status_t dc_serial_purge (dc_iostream_t *iostream, dc_direction_t direction);
+static dc_status_t dc_serial_sleep (dc_iostream_t *iostream, unsigned int milliseconds);
+static dc_status_t dc_serial_close (dc_iostream_t *iostream);
+
+typedef struct dc_serial_t {
+ dc_iostream_t base;
/*
* The file descriptor corresponding to the serial port.
*/
@@ -46,6 +63,25 @@ struct dc_serial_t {
int halfduplex;
unsigned int baudrate;
unsigned int nbits;
+} dc_serial_t;
+
+static const dc_iostream_vtable_t dc_serial_vtable = {
+ sizeof(dc_serial_t),
+ dc_serial_set_timeout, /* set_timeout */
+ dc_serial_set_latency, /* set_latency */
+ dc_serial_set_halfduplex, /* set_halfduplex */
+ dc_serial_set_break, /* set_break */
+ dc_serial_set_dtr, /* set_dtr */
+ dc_serial_set_rts, /* set_rts */
+ dc_serial_get_lines, /* get_lines */
+ dc_serial_get_available, /* get_received */
+ dc_serial_configure, /* configure */
+ dc_serial_read, /* read */
+ dc_serial_write, /* write */
+ dc_serial_flush, /* flush */
+ dc_serial_purge, /* purge */
+ dc_serial_sleep, /* sleep */
+ dc_serial_close, /* close */
};
static dc_status_t
@@ -120,19 +156,24 @@ dc_serial_enumerate (dc_serial_callback_t callback, void *userdata)
}
dc_status_t
-dc_serial_open (dc_serial_t **out, dc_context_t *context, const char *name)
+dc_serial_open (dc_iostream_t **out, dc_context_t *context, const char *name)
{
dc_status_t status = DC_STATUS_SUCCESS;
+ dc_serial_t *device = NULL;
- if (out == NULL)
+ if (out == NULL || name == NULL)
return DC_STATUS_INVALIDARGS;
- INFO (context, "Open: name=%s", name ? name : "");
+ // Are we using custom IO?
+ if (_dc_context_custom_io(context))
+ return dc_custom_io_serial_open(out, context, name);
+
+ INFO (context, "Open: name=%s", name);
// Build the device name.
const char *devname = NULL;
char buffer[MAX_PATH] = "\\\\.\\";
- if (name && strncmp (name, buffer, 4) != 0) {
+ if (strncmp (name, buffer, 4) != 0) {
size_t length = strlen (name) + 1;
if (length + 4 > sizeof (buffer))
return DC_STATUS_NOMEMORY;
@@ -143,22 +184,17 @@ dc_serial_open (dc_serial_t **out, dc_context_t *context, const char *name)
}
// Allocate memory.
- dc_serial_t *device = (dc_serial_t *) malloc (sizeof (dc_serial_t));
+ device = (dc_serial_t *) dc_iostream_allocate (context, &dc_serial_vtable);
if (device == NULL) {
SYSERROR (context, ERROR_OUTOFMEMORY);
return DC_STATUS_NOMEMORY;
}
- // Library context.
- device->context = context;
-
// Default to full-duplex.
device->halfduplex = 0;
device->baudrate = 0;
device->nbits = 0;
- RETURN_IF_CUSTOM_SERIAL(context, *out = device, open, context, name);
-
// Open the device.
device->hFile = CreateFileA (devname,
GENERIC_READ | GENERIC_WRITE, 0,
@@ -185,64 +221,51 @@ dc_serial_open (dc_serial_t **out, dc_context_t *context, const char *name)
goto error_close;
}
- *out = device;
+ *out = (dc_iostream_t *) device;
return DC_STATUS_SUCCESS;
error_close:
CloseHandle (device->hFile);
error_free:
- free (device);
+ dc_iostream_deallocate ((dc_iostream_t *) device);
return status;
}
-dc_status_t
-dc_serial_close (dc_serial_t *device)
+static dc_status_t
+dc_serial_close (dc_iostream_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
-
- if (device == NULL)
- return DC_STATUS_SUCCESS;
-
- RETURN_IF_CUSTOM_SERIAL(device->context, free(device), close);
+ dc_serial_t *device = (dc_serial_t *) abstract;
// Restore the initial communication settings and timeouts.
if (!SetCommState (device->hFile, &device->dcb) ||
!SetCommTimeouts (device->hFile, &device->timeouts)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
dc_status_set_error(&status, syserror (errcode));
}
// Close the device.
if (!CloseHandle (device->hFile)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
dc_status_set_error(&status, syserror (errcode));
}
- // Free memory.
- free (device);
-
return status;
}
-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)
+static dc_status_t
+dc_serial_configure (dc_iostream_t *abstract, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "Configure: baudrate=%i, databits=%i, parity=%i, stopbits=%i, flowcontrol=%i",
- baudrate, databits, parity, stopbits, flowcontrol);
-
- RETURN_IF_CUSTOM_SERIAL(device->context, , configure, baudrate, databits, parity, stopbits, flowcontrol);
+ dc_serial_t *device = (dc_serial_t *) abstract;
// Retrieve the current settings.
DCB dcb;
if (!GetCommState (device->hFile, &dcb)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
@@ -332,7 +355,7 @@ dc_serial_configure (dc_serial_t *device, unsigned int baudrate, unsigned int da
// Apply the new settings.
if (!SetCommState (device->hFile, &dcb)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
@@ -342,21 +365,16 @@ dc_serial_configure (dc_serial_t *device, unsigned int baudrate, unsigned int da
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_set_timeout (dc_serial_t *device, int timeout)
+static dc_status_t
+dc_serial_set_timeout (dc_iostream_t *abstract, int timeout)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "Timeout: value=%i", timeout);
-
- RETURN_IF_CUSTOM_SERIAL(device->context, , set_timeout, timeout);
+ dc_serial_t *device = (dc_serial_t *) abstract;
// Retrieve the current timeouts.
COMMTIMEOUTS timeouts;
if (!GetCommTimeouts (device->hFile, &timeouts)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
@@ -387,58 +405,39 @@ dc_serial_set_timeout (dc_serial_t *device, int timeout)
// Activate the new timeouts.
if (!SetCommTimeouts (device->hFile, &timeouts)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_set_halfduplex (dc_serial_t *device, unsigned int value)
+static dc_status_t
+dc_serial_set_halfduplex (dc_iostream_t *abstract, unsigned int value)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- RETURN_IF_CUSTOM_SERIAL(device->context, , set_halfduplex, value);
+ dc_serial_t *device = (dc_serial_t *) abstract;
device->halfduplex = value;
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_set_latency (dc_serial_t *device, unsigned int value)
+static dc_status_t
+dc_serial_set_latency (dc_iostream_t *abstract, unsigned int value)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_read (dc_serial_t *device, void *data, size_t size, size_t *actual)
+static dc_status_t
+dc_serial_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
{
- size_t nbytes = 0;
dc_status_t status = DC_STATUS_SUCCESS;
+ dc_serial_t *device = (dc_serial_t *) abstract;
DWORD dwRead = 0;
- if (device == NULL) {
- status = DC_STATUS_INVALIDARGS;
- goto out_invalidargs;
- }
-
- RETURN_IF_CUSTOM_SERIAL(device->context,
- {
- HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Custom Read", (unsigned char *) data, nbytes);
- if (actual)
- *actual = nbytes;
- },
- read, data, size, &nbytes);
-
if (!ReadFile (device->hFile, data, size, &dwRead, NULL)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
status = syserror (errcode);
goto out;
}
@@ -448,42 +447,26 @@ dc_serial_read (dc_serial_t *device, void *data, size_t size, size_t *actual)
}
out:
- HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Read", (unsigned char *) data, dwRead);
-
-out_invalidargs:
if (actual)
*actual = dwRead;
return status;
}
-dc_status_t
-dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *actual)
+static dc_status_t
+dc_serial_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual)
{
- size_t nbytes = 0;
dc_status_t status = DC_STATUS_SUCCESS;
+ dc_serial_t *device = (dc_serial_t *) abstract;
DWORD dwWritten = 0;
- if (device == NULL) {
- status = DC_STATUS_INVALIDARGS;
- goto out_invalidargs;
- }
-
- RETURN_IF_CUSTOM_SERIAL(device->context,
- {
- HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Custom Write", (unsigned char *) data, nbytes);
- if (actual)
- *actual = nbytes;
- },
- write, data, size, &nbytes);
-
LARGE_INTEGER begin, end, freq;
if (device->halfduplex) {
// Get the current time.
if (!QueryPerformanceFrequency(&freq) ||
!QueryPerformanceCounter(&begin)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
status = syserror (errcode);
goto out;
}
@@ -491,7 +474,7 @@ dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *act
if (!WriteFile (device->hFile, data, size, &dwWritten, NULL)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
status = syserror (errcode);
goto out;
}
@@ -500,7 +483,7 @@ dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *act
// Get the current time.
if (!QueryPerformanceCounter(&end)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
status = syserror (errcode);
goto out;
}
@@ -519,7 +502,7 @@ dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *act
// The remaining time is rounded up to the nearest millisecond
// because the Windows Sleep() function doesn't have a higher
// resolution.
- dc_serial_sleep (device, (remaining + 999) / 1000);
+ dc_serial_sleep (abstract, (remaining + 999) / 1000);
}
}
@@ -528,24 +511,16 @@ dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *act
}
out:
- HEXDUMP (device->context, DC_LOGLEVEL_INFO, "Write", (const unsigned char *) data, dwWritten);
-
-out_invalidargs:
if (actual)
*actual = dwWritten;
return status;
}
-dc_status_t
-dc_serial_purge (dc_serial_t *device, dc_direction_t direction)
+static dc_status_t
+dc_serial_purge (dc_iostream_t *abstract, dc_direction_t direction)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "Purge: direction=%u", direction);
-
- RETURN_IF_CUSTOM_SERIAL(device->context, , purge, direction);
+ dc_serial_t *device = (dc_serial_t *) abstract;
DWORD flags = 0;
@@ -565,50 +540,42 @@ dc_serial_purge (dc_serial_t *device, dc_direction_t direction)
if (!PurgeComm (device->hFile, flags)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_flush (dc_serial_t *device)
+static dc_status_t
+dc_serial_flush (dc_iostream_t *abstract)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "Flush: none");
+ dc_serial_t *device = (dc_serial_t *) abstract;
if (!FlushFileBuffers (device->hFile)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_set_break (dc_serial_t *device, unsigned int level)
+static dc_status_t
+dc_serial_set_break (dc_iostream_t *abstract, unsigned int level)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "Break: value=%i", level);
-
- RETURN_IF_CUSTOM_SERIAL(device->context, , set_break, level);
+ dc_serial_t *device = (dc_serial_t *) abstract;
if (level) {
if (!SetCommBreak (device->hFile)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
} else {
if (!ClearCommBreak (device->hFile)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
}
@@ -616,61 +583,48 @@ dc_serial_set_break (dc_serial_t *device, unsigned int level)
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_set_dtr (dc_serial_t *device, unsigned int level)
+static dc_status_t
+dc_serial_set_dtr (dc_iostream_t *abstract, unsigned int level)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "DTR: value=%i", level);
-
- RETURN_IF_CUSTOM_SERIAL(device->context, , set_dtr, level);
+ dc_serial_t *device = (dc_serial_t *) abstract;
int status = (level ? SETDTR : CLRDTR);
if (!EscapeCommFunction (device->hFile, status)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_set_rts (dc_serial_t *device, unsigned int level)
+static dc_status_t
+dc_serial_set_rts (dc_iostream_t *abstract, unsigned int level)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "RTS: value=%i", level);
-
- RETURN_IF_CUSTOM_SERIAL(device->context, , set_rts, level);
+ dc_serial_t *device = (dc_serial_t *) abstract;
int status = (level ? SETRTS : CLRRTS);
if (!EscapeCommFunction (device->hFile, status)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_get_available (dc_serial_t *device, size_t *value)
+static dc_status_t
+dc_serial_get_available (dc_iostream_t *abstract, size_t *value)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- RETURN_IF_CUSTOM_SERIAL(device->context, , get_available, value);
+ dc_serial_t *device = (dc_serial_t *) abstract;
COMSTAT stats;
if (!ClearCommError (device->hFile, NULL, &stats)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
@@ -680,18 +634,16 @@ dc_serial_get_available (dc_serial_t *device, size_t *value)
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_get_lines (dc_serial_t *device, unsigned int *value)
+static dc_status_t
+dc_serial_get_lines (dc_iostream_t *abstract, unsigned int *value)
{
+ dc_serial_t *device = (dc_serial_t *) abstract;
unsigned int lines = 0;
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
DWORD stats = 0;
if (!GetCommModemStatus (device->hFile, &stats)) {
DWORD errcode = GetLastError ();
- SYSERROR (device->context, errcode);
+ SYSERROR (abstract->context, errcode);
return syserror (errcode);
}
@@ -710,14 +662,9 @@ dc_serial_get_lines (dc_serial_t *device, unsigned int *value)
return DC_STATUS_SUCCESS;
}
-dc_status_t
-dc_serial_sleep (dc_serial_t *device, unsigned int timeout)
+static dc_status_t
+dc_serial_sleep (dc_iostream_t *abstract, unsigned int timeout)
{
- if (device == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (device->context, "Sleep: value=%u", timeout);
-
Sleep (timeout);
return DC_STATUS_SUCCESS;
diff --git a/src/shearwater_common.c b/src/shearwater_common.c
index 58fd3a3..bad14c8 100644
--- a/src/shearwater_common.c
+++ b/src/shearwater_common.c
@@ -41,21 +41,21 @@ shearwater_common_open (shearwater_common_device_t *device, dc_context_t *contex
dc_status_t status = DC_STATUS_SUCCESS;
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
return status;
}
// Set the serial communication protocol (115200 8N1).
- status = dc_serial_configure (device->port, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (3000ms).
- status = dc_serial_set_timeout (device->port, 3000);
+ status = dc_iostream_set_timeout (device->iostream, 3000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
status = DC_STATUS_IO;
@@ -63,13 +63,13 @@ shearwater_common_open (shearwater_common_device_t *device, dc_context_t *contex
}
// Make sure everything is in a sane state.
- dc_serial_sleep (device->port, 300);
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_sleep (device->iostream, 300);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
return status;
}
@@ -78,7 +78,7 @@ dc_status_t
shearwater_common_close (shearwater_common_device_t *device)
{
// Close the device.
- return dc_serial_close (device->port);
+ return dc_iostream_close (device->iostream);
}
@@ -154,7 +154,7 @@ 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.
- status = dc_serial_write (device->port, end, sizeof (end), NULL);
+ status = dc_iostream_write (device->iostream, end, sizeof (end), NULL);
if (status != DC_STATUS_SUCCESS) {
return status;
}
@@ -183,7 +183,7 @@ shearwater_common_slip_write (shearwater_common_device_t *device, const unsigned
// Flush the buffer if necessary.
if (nbytes + len + sizeof(end) > sizeof(buffer)) {
- status = dc_serial_write (device->port, buffer, nbytes, NULL);
+ status = dc_iostream_write (device->iostream, buffer, nbytes, NULL);
if (status != DC_STATUS_SUCCESS) {
return status;
}
@@ -201,7 +201,7 @@ shearwater_common_slip_write (shearwater_common_device_t *device, const unsigned
nbytes += sizeof(end);
// Flush the buffer.
- status = dc_serial_write (device->port, buffer, nbytes, NULL);
+ status = dc_iostream_write (device->iostream, buffer, nbytes, NULL);
if (status != DC_STATUS_SUCCESS) {
return status;
}
@@ -224,7 +224,7 @@ shearwater_common_slip_read (shearwater_common_device_t *device, unsigned char d
unsigned char c = 0;
// Get a single character to process.
- status = dc_serial_read (device->port, &c, 1, NULL);
+ status = dc_iostream_read (device->iostream, &c, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
return status;
}
@@ -243,7 +243,7 @@ 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.
- status = dc_serial_read (device->port, &c, 1, NULL);
+ status = dc_iostream_read (device->iostream, &c, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
return status;
}
diff --git a/src/shearwater_common.h b/src/shearwater_common.h
index 4253a00..4e3a561 100644
--- a/src/shearwater_common.h
+++ b/src/shearwater_common.h
@@ -44,7 +44,7 @@ extern "C" {
typedef struct shearwater_common_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
} shearwater_common_device_t;
dc_status_t
diff --git a/src/shearwater_predator_parser.c b/src/shearwater_predator_parser.c
index 6e81083..16b458a 100644
--- a/src/shearwater_predator_parser.c
+++ b/src/shearwater_predator_parser.c
@@ -408,7 +408,7 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
// Status flags.
unsigned int status = data[offset + 11];
if ((status & OC) == 0) {
- mode = DC_DIVEMODE_CC;
+ mode = DC_DIVEMODE_CCR;
}
// Gaschange.
diff --git a/src/socket.c b/src/socket.c
new file mode 100644
index 0000000..5ce392f
--- /dev/null
+++ b/src/socket.c
@@ -0,0 +1,358 @@
+/*
+ * libdivecomputer
+ *
+ * Copyright (C) 2017 Jef Driesen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include "socket.h"
+
+#include "common-private.h"
+#include "context-private.h"
+
+dc_status_t
+dc_socket_syserror (s_errcode_t errcode)
+{
+ switch (errcode) {
+ case S_EINVAL:
+ return DC_STATUS_INVALIDARGS;
+ case S_ENOMEM:
+ return DC_STATUS_NOMEMORY;
+ case S_EACCES:
+ return DC_STATUS_NOACCESS;
+ case S_EAFNOSUPPORT:
+ return DC_STATUS_UNSUPPORTED;
+ default:
+ return DC_STATUS_IO;
+ }
+}
+
+dc_status_t
+dc_socket_init (dc_context_t *context)
+{
+#ifdef _WIN32
+ // Initialize the winsock dll.
+ WSADATA wsaData;
+ WORD wVersionRequested = MAKEWORD (2, 2);
+ int rc = WSAStartup (wVersionRequested, &wsaData);
+ if (rc != 0) {
+ SYSERROR (context, rc);
+ return DC_STATUS_UNSUPPORTED;
+ }
+
+ // Confirm that the winsock dll supports version 2.2.
+ // Note that if the dll supports versions greater than 2.2 in addition to
+ // 2.2, it will still return 2.2 since that is the version we requested.
+ if (LOBYTE (wsaData.wVersion) != 2 ||
+ HIBYTE (wsaData.wVersion) != 2) {
+ ERROR (context, "Incorrect winsock version.");
+ return DC_STATUS_UNSUPPORTED;
+ }
+#endif
+
+ return DC_STATUS_SUCCESS;
+}
+
+dc_status_t
+dc_socket_exit (dc_context_t *context)
+{
+#ifdef _WIN32
+ // Terminate the winsock dll.
+ if (WSACleanup () != 0) {
+ s_errcode_t errcode = S_ERRNO;
+ SYSERROR (context, errcode);
+ return dc_socket_syserror(errcode);
+ }
+#endif
+
+ return DC_STATUS_SUCCESS;
+}
+
+dc_status_t
+dc_socket_open (dc_iostream_t *abstract, int family, int type, int protocol)
+{
+ dc_status_t status = DC_STATUS_SUCCESS;
+ dc_socket_t *device = (dc_socket_t *) abstract;
+
+ // Default to blocking reads.
+ device->timeout = -1;
+
+ // Initialize the socket library.
+ status = dc_socket_init (abstract->context);
+ if (status != DC_STATUS_SUCCESS) {
+ return status;
+ }
+
+ // Open the socket.
+ device->fd = socket (family, type, protocol);
+ if (device->fd == S_INVALID) {
+ s_errcode_t errcode = S_ERRNO;
+ SYSERROR (abstract->context, errcode);
+ status = dc_socket_syserror(errcode);
+ goto error;
+ }
+
+ return DC_STATUS_SUCCESS;
+
+error:
+ dc_socket_exit (abstract->context);
+ return status;
+}
+
+dc_status_t
+dc_socket_close (dc_iostream_t *abstract)
+{
+ dc_status_t status = DC_STATUS_SUCCESS;
+ dc_socket_t *socket = (dc_socket_t *) abstract;
+ dc_status_t rc = DC_STATUS_SUCCESS;
+
+ // Terminate all send and receive operations.
+ shutdown (socket->fd, 0);
+
+ // Close the socket.
+ if (S_CLOSE (socket->fd) != 0) {
+ s_errcode_t errcode = S_ERRNO;
+ SYSERROR (abstract->context, errcode);
+ dc_status_set_error(&status, dc_socket_syserror(errcode));
+ }
+
+ // Terminate the socket library.
+ rc = dc_socket_exit (abstract->context);
+ if (rc != DC_STATUS_SUCCESS) {
+ dc_status_set_error(&status, rc);
+ }
+
+ return status;
+}
+
+dc_status_t
+dc_socket_connect (dc_iostream_t *abstract, const struct sockaddr *addr, s_socklen_t addrlen)
+{
+ dc_socket_t *socket = (dc_socket_t *) abstract;
+
+ if (connect (socket->fd, addr, addrlen) != 0) {
+ s_errcode_t errcode = S_ERRNO;
+ SYSERROR (abstract->context, errcode);
+ return dc_socket_syserror(errcode);
+ }
+
+ return DC_STATUS_SUCCESS;
+}
+
+dc_status_t
+dc_socket_set_timeout (dc_iostream_t *abstract, int timeout)
+{
+ dc_socket_t *socket = (dc_socket_t *) abstract;
+
+ socket->timeout = timeout;
+
+ return DC_STATUS_SUCCESS;
+}
+
+dc_status_t
+dc_socket_set_latency (dc_iostream_t *iostream, unsigned int value)
+{
+ return DC_STATUS_SUCCESS;
+}
+
+dc_status_t
+dc_socket_set_halfduplex (dc_iostream_t *iostream, unsigned int value)
+{
+ return DC_STATUS_SUCCESS;
+}
+
+dc_status_t
+dc_socket_set_break (dc_iostream_t *iostream, unsigned int value)
+{
+ return DC_STATUS_SUCCESS;
+}
+
+dc_status_t
+dc_socket_set_dtr (dc_iostream_t *iostream, unsigned int value)
+{
+ return DC_STATUS_SUCCESS;
+}
+
+dc_status_t
+dc_socket_set_rts (dc_iostream_t *iostream, unsigned int value)
+{
+ return DC_STATUS_SUCCESS;
+}
+
+dc_status_t
+dc_socket_get_lines (dc_iostream_t *iostream, unsigned int *value)
+{
+ if (value)
+ *value = 0;
+
+ return DC_STATUS_SUCCESS;
+}
+
+dc_status_t
+dc_socket_get_available (dc_iostream_t *abstract, size_t *value)
+{
+ dc_socket_t *socket = (dc_socket_t *) abstract;
+
+#ifdef _WIN32
+ unsigned long bytes = 0;
+#else
+ int bytes = 0;
+#endif
+
+ if (S_IOCTL (socket->fd, FIONREAD, &bytes) != 0) {
+ s_errcode_t errcode = S_ERRNO;
+ SYSERROR (abstract->context, errcode);
+ return dc_socket_syserror(errcode);
+ }
+
+ if (value)
+ *value = bytes;
+
+ return DC_STATUS_SUCCESS;
+}
+
+dc_status_t
+dc_socket_configure (dc_iostream_t *abstract, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol)
+{
+ return DC_STATUS_SUCCESS;
+}
+
+dc_status_t
+dc_socket_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
+{
+ dc_status_t status = DC_STATUS_SUCCESS;
+ dc_socket_t *socket = (dc_socket_t *) abstract;
+ size_t nbytes = 0;
+
+ while (nbytes < size) {
+ fd_set fds;
+ FD_ZERO (&fds);
+ FD_SET (socket->fd, &fds);
+
+ struct timeval tvt;
+ if (socket->timeout > 0) {
+ tvt.tv_sec = (socket->timeout / 1000);
+ tvt.tv_usec = (socket->timeout % 1000) * 1000;
+ } else if (socket->timeout == 0) {
+ timerclear (&tvt);
+ }
+
+ int rc = select (socket->fd + 1, &fds, NULL, NULL, socket->timeout >= 0 ? &tvt : NULL);
+ if (rc < 0) {
+ s_errcode_t errcode = S_ERRNO;
+ if (errcode == S_EINTR)
+ continue; // Retry.
+ SYSERROR (abstract->context, errcode);
+ status = dc_socket_syserror(errcode);
+ goto out;
+ } else if (rc == 0) {
+ break; // Timeout.
+ }
+
+ s_ssize_t n = recv (socket->fd, (char *) data + nbytes, size - nbytes, 0);
+ if (n < 0) {
+ s_errcode_t errcode = S_ERRNO;
+ if (errcode == S_EINTR || errcode == S_EAGAIN)
+ continue; // Retry.
+ SYSERROR (abstract->context, errcode);
+ status = dc_socket_syserror(errcode);
+ goto out;
+ } else if (n == 0) {
+ break; // EOF reached.
+ }
+
+ nbytes += n;
+ }
+
+ if (nbytes != size) {
+ status = DC_STATUS_TIMEOUT;
+ }
+
+out:
+ if (actual)
+ *actual = nbytes;
+
+ return status;
+}
+
+dc_status_t
+dc_socket_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual)
+{
+ dc_status_t status = DC_STATUS_SUCCESS;
+ dc_socket_t *socket = (dc_socket_t *) abstract;
+ size_t nbytes = 0;
+
+ while (nbytes < size) {
+ fd_set fds;
+ FD_ZERO (&fds);
+ FD_SET (socket->fd, &fds);
+
+ int rc = select (socket->fd + 1, NULL, &fds, NULL, NULL);
+ if (rc < 0) {
+ s_errcode_t errcode = S_ERRNO;
+ if (errcode == S_EINTR)
+ continue; // Retry.
+ SYSERROR (abstract->context, errcode);
+ status = dc_socket_syserror(errcode);
+ goto out;
+ } else if (rc == 0) {
+ break; // Timeout.
+ }
+
+ s_ssize_t n = send (socket->fd, (const char *) data + nbytes, size - nbytes, 0);
+ if (n < 0) {
+ s_errcode_t errcode = S_ERRNO;
+ if (errcode == S_EINTR || errcode == S_EAGAIN)
+ continue; // Retry.
+ SYSERROR (abstract->context, errcode);
+ status = dc_socket_syserror(errcode);
+ goto out;
+ } else if (n == 0) {
+ break; // EOF.
+ }
+
+ nbytes += n;
+ }
+
+ if (nbytes != size) {
+ status = DC_STATUS_TIMEOUT;
+ }
+
+out:
+ if (actual)
+ *actual = nbytes;
+
+ return status;
+}
+
+dc_status_t
+dc_socket_flush (dc_iostream_t *abstract)
+{
+ return DC_STATUS_SUCCESS;
+}
+
+dc_status_t
+dc_socket_purge (dc_iostream_t *abstract, dc_direction_t direction)
+{
+ return DC_STATUS_SUCCESS;
+}
+
+dc_status_t
+dc_socket_sleep (dc_iostream_t *abstract, unsigned int timeout)
+{
+ return DC_STATUS_SUCCESS;
+}
diff --git a/src/socket.h b/src/socket.h
new file mode 100644
index 0000000..d612603
--- /dev/null
+++ b/src/socket.h
@@ -0,0 +1,152 @@
+/*
+ * libdivecomputer
+ *
+ * Copyright (C) 2017 Jef Driesen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#ifndef DC_SOCKET_H
+#define DC_SOCKET_H
+
+#ifdef _WIN32
+#define NOGDI
+#include
+#include
+#else
+#include // errno
+#include // close
+#include // socket, getsockopt
+#include // socket, getsockopt
+#include // select
+#include // ioctl
+#include
+#endif
+
+#include
+#include
+
+#include "iostream-private.h"
+
+#ifdef _WIN32
+typedef SOCKET s_socket_t;
+typedef int s_ssize_t;
+typedef DWORD s_errcode_t;
+typedef int s_socklen_t;
+#define S_ERRNO WSAGetLastError ()
+#define S_EINTR WSAEINTR
+#define S_EAGAIN WSAEWOULDBLOCK
+#define S_ENOMEM WSA_NOT_ENOUGH_MEMORY
+#define S_EINVAL WSAEINVAL
+#define S_EACCES WSAEACCES
+#define S_EAFNOSUPPORT WSAEAFNOSUPPORT
+#define S_INVALID INVALID_SOCKET
+#define S_IOCTL ioctlsocket
+#define S_CLOSE closesocket
+#else
+typedef int s_socket_t;
+typedef ssize_t s_ssize_t;
+typedef int s_errcode_t;
+typedef socklen_t s_socklen_t;
+#define S_ERRNO errno
+#define S_EINTR EINTR
+#define S_EAGAIN EAGAIN
+#define S_ENOMEM ENOMEM
+#define S_EINVAL EINVAL
+#define S_EACCES EACCES
+#define S_EAFNOSUPPORT EAFNOSUPPORT
+#define S_INVALID -1
+#define S_IOCTL ioctl
+#define S_CLOSE close
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct dc_socket_t {
+ dc_iostream_t base;
+ s_socket_t fd;
+ int timeout;
+} dc_socket_t;
+
+dc_status_t
+dc_socket_syserror (s_errcode_t errcode);
+
+dc_status_t
+dc_socket_init (dc_context_t *context);
+
+dc_status_t
+dc_socket_exit (dc_context_t *context);
+
+dc_status_t
+dc_socket_open (dc_iostream_t *iostream, int family, int type, int protocol);
+
+dc_status_t
+dc_socket_close (dc_iostream_t *iostream);
+
+dc_status_t
+dc_socket_connect (dc_iostream_t *iostream, const struct sockaddr *addr, s_socklen_t addrlen);
+
+dc_status_t
+dc_socket_set_timeout (dc_iostream_t *iostream, int timeout);
+
+dc_status_t
+dc_socket_set_latency (dc_iostream_t *iostream, unsigned int value);
+
+dc_status_t
+dc_socket_set_halfduplex (dc_iostream_t *iostream, unsigned int value);
+
+dc_status_t
+dc_socket_set_break (dc_iostream_t *iostream, unsigned int value);
+
+dc_status_t
+dc_socket_set_dtr (dc_iostream_t *iostream, unsigned int value);
+
+dc_status_t
+dc_socket_set_rts (dc_iostream_t *iostream, unsigned int value);
+
+dc_status_t
+dc_socket_get_lines (dc_iostream_t *iostream, unsigned int *value);
+
+dc_status_t
+dc_socket_get_available (dc_iostream_t *iostream, size_t *value);
+
+dc_status_t
+dc_socket_configure (dc_iostream_t *iostream, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
+
+dc_status_t
+dc_socket_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
+
+dc_status_t
+dc_socket_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
+
+dc_status_t
+dc_socket_flush (dc_iostream_t *iostream);
+
+dc_status_t
+dc_socket_purge (dc_iostream_t *iostream, dc_direction_t direction);
+
+dc_status_t
+dc_socket_sleep (dc_iostream_t *iostream, unsigned int milliseconds);
+
+dc_status_t
+dc_socket_close (dc_iostream_t *iostream);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* DC_SOCKET_H */
diff --git a/src/suunto_d9.c b/src/suunto_d9.c
index 6f5b81c..2c92a49 100644
--- a/src/suunto_d9.c
+++ b/src/suunto_d9.c
@@ -44,7 +44,7 @@
typedef struct suunto_d9_device_t {
suunto_common2_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
} 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);
@@ -111,7 +111,7 @@ suunto_d9_device_autodetect (suunto_d9_device_t *device, unsigned int model)
unsigned int idx = (hint + i) % C_ARRAY_SIZE(baudrates);
// Adjust the baudrate.
- status = dc_serial_configure (device->port, baudrates[idx], 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 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 status;
@@ -147,41 +147,41 @@ suunto_d9_device_open (dc_device_t **out, dc_context_t *context, const char *nam
suunto_common2_device_init (&device->base);
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (9600 8N1).
- status = dc_serial_configure (device->port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (3000 ms).
- status = dc_serial_set_timeout (device->port, 3000);
+ status = dc_iostream_set_timeout (device->iostream, 3000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Set the DTR line (power supply for the interface).
- status = dc_serial_set_dtr (device->port, 1);
+ status = dc_iostream_set_dtr (device->iostream, 1);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the DTR line.");
goto error_close;
}
// Give the interface 100 ms to settle and draw power up.
- dc_serial_sleep (device->port, 100);
+ dc_iostream_sleep (device->iostream, 100);
// Make sure everything is in a sane state.
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
// Try to autodetect the protocol variant.
status = suunto_d9_device_autodetect (device, model);
@@ -206,7 +206,7 @@ suunto_d9_device_open (dc_device_t **out, dc_context_t *context, const char *nam
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -221,7 +221,7 @@ suunto_d9_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -240,10 +240,10 @@ suunto_d9_device_packet (dc_device_t *abstract, const unsigned char command[], u
return DC_STATUS_CANCELLED;
// Clear RTS to send the command.
- dc_serial_set_rts (device->port, 0);
+ dc_iostream_set_rts (device->iostream, 0);
// Send the command to the dive computer.
- status = dc_serial_write (device->port, command, csize, NULL);
+ status = dc_iostream_write (device->iostream, command, csize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -252,7 +252,7 @@ suunto_d9_device_packet (dc_device_t *abstract, const unsigned char command[], u
// Receive the echo.
unsigned char echo[128] = {0};
assert (sizeof (echo) >= csize);
- status = dc_serial_read (device->port, echo, csize, NULL);
+ status = dc_iostream_read (device->iostream, echo, csize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the echo.");
return status;
@@ -265,10 +265,10 @@ suunto_d9_device_packet (dc_device_t *abstract, const unsigned char command[], u
}
// Set RTS to receive the reply.
- dc_serial_set_rts (device->port, 1);
+ dc_iostream_set_rts (device->iostream, 1);
// Receive the answer of the dive computer.
- status = dc_serial_read (device->port, answer, asize, NULL);
+ status = dc_iostream_read (device->iostream, answer, asize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c
index e8908c5..6566bc9 100644
--- a/src/suunto_d9_parser.c
+++ b/src/suunto_d9_parser.c
@@ -389,7 +389,7 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne
*((dc_divemode_t *) value) = DC_DIVEMODE_FREEDIVE;
break;
case CCR:
- *((dc_divemode_t *) value) = DC_DIVEMODE_CC;
+ *((dc_divemode_t *) value) = DC_DIVEMODE_CCR;
break;
default:
return DC_STATUS_DATAFORMAT;
diff --git a/src/suunto_eon.c b/src/suunto_eon.c
index 2875654..f41fae6 100644
--- a/src/suunto_eon.c
+++ b/src/suunto_eon.c
@@ -36,7 +36,7 @@
typedef struct suunto_eon_device_t {
suunto_common_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
} suunto_eon_device_t;
static dc_status_t suunto_eon_device_dump (dc_device_t *abstract, dc_buffer_t *buffer);
@@ -84,31 +84,31 @@ suunto_eon_device_open (dc_device_t **out, dc_context_t *context, const char *na
suunto_common_device_init (&device->base);
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (1200 8N2).
- status = dc_serial_configure (device->port, 1200, 8, DC_PARITY_NONE, DC_STOPBITS_TWO, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 1200, 8, DC_PARITY_NONE, DC_STOPBITS_TWO, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (1000ms).
- status = dc_serial_set_timeout (device->port, 1000);
+ status = dc_iostream_set_timeout (device->iostream, 1000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Clear the RTS line.
- status = dc_serial_set_rts (device->port, 0);
+ status = dc_iostream_set_rts (device->iostream, 0);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the DTR/RTS line.");
goto error_close;
@@ -119,7 +119,7 @@ suunto_eon_device_open (dc_device_t **out, dc_context_t *context, const char *na
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -134,7 +134,7 @@ suunto_eon_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -163,7 +163,7 @@ suunto_eon_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
// Send the command.
unsigned char command[1] = {'P'};
- status = dc_serial_write (device->port, command, sizeof (command), NULL);
+ status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -178,7 +178,7 @@ suunto_eon_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
// Increase the packet size if more data is immediately available.
size_t available = 0;
- status = dc_serial_get_available (device->port, &available);
+ status = dc_iostream_get_available (device->iostream, &available);
if (status == DC_STATUS_SUCCESS && available > len)
len = available;
@@ -187,7 +187,7 @@ suunto_eon_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
len = sizeof(answer) - nbytes;
// Read the packet.
- status = dc_serial_read (device->port, answer + nbytes, len, NULL);
+ status = dc_iostream_read (device->iostream, answer + nbytes, len, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -264,7 +264,7 @@ 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);
- status = dc_serial_write (device->port, command, sizeof (command), NULL);
+ status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -285,7 +285,7 @@ suunto_eon_device_write_interval (dc_device_t *abstract, unsigned char interval)
// Send the command.
unsigned char command[2] = {'T', interval};
- status = dc_serial_write (device->port, command, sizeof (command), NULL);
+ status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
diff --git a/src/suunto_eonsteel_parser.c b/src/suunto_eonsteel_parser.c
index 30dd9a4..429e862 100644
--- a/src/suunto_eonsteel_parser.c
+++ b/src/suunto_eonsteel_parser.c
@@ -1351,7 +1351,7 @@ static int traverse_diving_fields(suunto_eonsteel_parser_t *eon, const struct ty
if (!strcmp(name, "DiveMode")) {
if (!strncmp((const char *)data, "CCR", 3)) {
- eon->cache.divemode = DC_DIVEMODE_CC;
+ eon->cache.divemode = DC_DIVEMODE_CCR;
eon->cache.initialized |= 1 << DC_FIELD_DIVEMODE;
}
return add_string(eon, "Dive Mode", data);
diff --git a/src/suunto_solution.c b/src/suunto_solution.c
index cb2481d..2e9e14e 100644
--- a/src/suunto_solution.c
+++ b/src/suunto_solution.c
@@ -39,7 +39,7 @@
typedef struct suunto_solution_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
} suunto_solution_device_t;
static dc_status_t suunto_solution_device_dump (dc_device_t *abstract, dc_buffer_t *buffer);
@@ -78,31 +78,31 @@ suunto_solution_device_open (dc_device_t **out, dc_context_t *context, const cha
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (1200 8N2).
- status = dc_serial_configure (device->port, 1200, 8, DC_PARITY_NONE, DC_STOPBITS_TWO, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 1200, 8, DC_PARITY_NONE, DC_STOPBITS_TWO, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (1000ms).
- status = dc_serial_set_timeout (device->port, 1000);
+ status = dc_iostream_set_timeout (device->iostream, 1000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Clear the RTS line.
- status = dc_serial_set_rts (device->port, 0);
+ status = dc_iostream_set_rts (device->iostream, 0);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the DTR/RTS line.");
goto error_close;
@@ -113,7 +113,7 @@ suunto_solution_device_open (dc_device_t **out, dc_context_t *context, const cha
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -128,7 +128,7 @@ suunto_solution_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -161,14 +161,14 @@ suunto_solution_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
unsigned char answer[3] = {0};
// Assert DTR
- dc_serial_set_dtr (device->port, 1);
+ dc_iostream_set_dtr (device->iostream, 1);
// Send: 0xFF
command[0] = 0xFF;
- dc_serial_write (device->port, command, 1, NULL);
+ dc_iostream_write (device->iostream, command, 1, NULL);
// Receive: 0x3F
- status = dc_serial_read (device->port, answer, 1, NULL);
+ status = dc_iostream_read (device->iostream, answer, 1, NULL);
if (status != DC_STATUS_SUCCESS)
return status;
if (answer[0] != 0x3F)
@@ -178,7 +178,7 @@ suunto_solution_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
command[0] = 0x4D;
command[1] = 0x01;
command[2] = 0x01;
- dc_serial_write (device->port, command, 3, NULL);
+ dc_iostream_write (device->iostream, command, 3, NULL);
// Update and emit a progress event.
progress.current += 1;
@@ -187,7 +187,7 @@ 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]
- status = dc_serial_read (device->port, answer, 3, NULL);
+ status = dc_iostream_read (device->iostream, answer, 3, NULL);
if (status != DC_STATUS_SUCCESS)
return status;
if (answer[0] != 0x01 || answer[1] != i)
@@ -195,10 +195,10 @@ suunto_solution_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
// Send: i
command[0] = i;
- dc_serial_write (device->port, command, 1, NULL);
+ dc_iostream_write (device->iostream, command, 1, NULL);
// Receive: data[i]
- status = dc_serial_read (device->port, data + i, 1, NULL);
+ status = dc_iostream_read (device->iostream, data + i, 1, NULL);
if (status != DC_STATUS_SUCCESS)
return status;
if (data[i] != answer[2])
@@ -206,7 +206,7 @@ suunto_solution_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
// Send: 0x0D
command[0] = 0x0D;
- dc_serial_write (device->port, command, 1, NULL);
+ dc_iostream_write (device->iostream, command, 1, NULL);
// Update and emit a progress event.
progress.current += 1;
@@ -214,7 +214,7 @@ suunto_solution_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
}
// Receive: 0x02, 0x00, 0x80
- status = dc_serial_read (device->port, answer, 3, NULL);
+ status = dc_iostream_read (device->iostream, answer, 3, NULL);
if (status != DC_STATUS_SUCCESS)
return status;
if (answer[0] != 0x02 || answer[1] != 0x00 || answer[2] != 0x80)
@@ -222,10 +222,10 @@ suunto_solution_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
// Send: 0x80
command[0] = 0x80;
- dc_serial_write (device->port, command, 1, NULL);
+ dc_iostream_write (device->iostream, command, 1, NULL);
// Receive: 0x80
- status = dc_serial_read (device->port, answer, 1, NULL);
+ status = dc_iostream_read (device->iostream, answer, 1, NULL);
if (status != DC_STATUS_SUCCESS)
return status;
if (answer[0] != 0x80)
@@ -233,10 +233,10 @@ suunto_solution_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
// Send: 0x20
command[0] = 0x20;
- dc_serial_write (device->port, command, 1, NULL);
+ dc_iostream_write (device->iostream, command, 1, NULL);
// Receive: 0x3F
- status = dc_serial_read (device->port, answer, 1, NULL);
+ status = dc_iostream_read (device->iostream, answer, 1, NULL);
if (status != DC_STATUS_SUCCESS)
return status;
if (answer[0] != 0x3F)
diff --git a/src/suunto_vyper.c b/src/suunto_vyper.c
index 33657dc..ba5ad20 100644
--- a/src/suunto_vyper.c
+++ b/src/suunto_vyper.c
@@ -46,7 +46,7 @@
typedef struct suunto_vyper_device_t {
suunto_common_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
} 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);
@@ -104,48 +104,48 @@ suunto_vyper_device_open (dc_device_t **out, dc_context_t *context, const char *
suunto_common_device_init (&device->base);
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (2400 8O1).
- status = dc_serial_configure (device->port, 2400, 8, DC_PARITY_ODD, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 2400, 8, DC_PARITY_ODD, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (1000 ms).
- status = dc_serial_set_timeout (device->port, 1000);
+ status = dc_iostream_set_timeout (device->iostream, 1000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Set the DTR line (power supply for the interface).
- status = dc_serial_set_dtr (device->port, 1);
+ status = dc_iostream_set_dtr (device->iostream, 1);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the DTR line.");
goto error_close;
}
// Give the interface 100 ms to settle and draw power up.
- dc_serial_sleep (device->port, 100);
+ dc_iostream_sleep (device->iostream, 100);
// Make sure everything is in a sane state.
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
*out = (dc_device_t*) device;
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -160,7 +160,7 @@ suunto_vyper_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -175,13 +175,13 @@ suunto_vyper_send (suunto_vyper_device_t *device, const unsigned char command[],
dc_status_t status = DC_STATUS_SUCCESS;
dc_device_t *abstract = (dc_device_t *) device;
- dc_serial_sleep (device->port, 500);
+ dc_iostream_sleep (device->iostream, 500);
// Set RTS to send the command.
- dc_serial_set_rts (device->port, 1);
+ dc_iostream_set_rts (device->iostream, 1);
// Send the command to the dive computer.
- status = dc_serial_write (device->port, command, csize, NULL);
+ status = dc_iostream_write (device->iostream, command, csize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -198,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.
- dc_serial_sleep (device->port, 200);
- dc_serial_purge (device->port, DC_DIRECTION_INPUT);
+ dc_iostream_sleep (device->iostream, 200);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_INPUT);
// Clear RTS to receive the reply.
- dc_serial_set_rts (device->port, 0);
+ dc_iostream_set_rts (device->iostream, 0);
return DC_STATUS_SUCCESS;
}
@@ -227,7 +227,7 @@ suunto_vyper_transfer (suunto_vyper_device_t *device, const unsigned char comman
}
// Receive the answer of the dive computer.
- status = dc_serial_read (device->port, answer, asize, NULL);
+ status = dc_iostream_read (device->iostream, answer, asize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -352,7 +352,7 @@ suunto_vyper_read_dive (dc_device_t *abstract, dc_buffer_t *buffer, int init, dc
// Receive the header of the package.
size_t n = 0;
unsigned char answer[SZ_PACKET + 3] = {0};
- status = dc_serial_read (device->port, answer, 2, &n);
+ status = dc_iostream_read (device->iostream, 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
@@ -377,7 +377,7 @@ 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];
- status = dc_serial_read (device->port, answer + 2, len + 1, NULL);
+ status = dc_iostream_read (device->iostream, answer + 2, len + 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
diff --git a/src/suunto_vyper2.c b/src/suunto_vyper2.c
index 618ee4a..6ddd3d7 100644
--- a/src/suunto_vyper2.c
+++ b/src/suunto_vyper2.c
@@ -35,7 +35,7 @@
typedef struct suunto_vyper2_device_t {
suunto_common2_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
} 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);
@@ -93,44 +93,44 @@ suunto_vyper2_device_open (dc_device_t **out, dc_context_t *context, const char
suunto_common2_device_init (&device->base);
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (9600 8N1).
- status = dc_serial_configure (device->port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (3000 ms).
- status = dc_serial_set_timeout (device->port, 3000);
+ status = dc_iostream_set_timeout (device->iostream, 3000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Set the DTR line (power supply for the interface).
- status = dc_serial_set_dtr (device->port, 1);
+ status = dc_iostream_set_dtr (device->iostream, 1);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the DTR line.");
goto error_close;
}
// Give the interface 100 ms to settle and draw power up.
- dc_serial_sleep (device->port, 100);
+ dc_iostream_sleep (device->iostream, 100);
// Make sure everything is in a sane state.
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
// Enable half-duplex emulation.
- dc_serial_set_halfduplex (device->port, 1);
+ dc_iostream_set_halfduplex (device->iostream, 1);
// Read the version info.
status = suunto_common2_device_version ((dc_device_t *) device, device->base.version, sizeof (device->base.version));
@@ -151,7 +151,7 @@ suunto_vyper2_device_open (dc_device_t **out, dc_context_t *context, const char
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -166,7 +166,7 @@ suunto_vyper2_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -184,23 +184,23 @@ suunto_vyper2_device_packet (dc_device_t *abstract, const unsigned char command[
if (device_is_cancelled (abstract))
return DC_STATUS_CANCELLED;
- dc_serial_sleep (device->port, 600);
+ dc_iostream_sleep (device->iostream, 600);
// Set RTS to send the command.
- dc_serial_set_rts (device->port, 1);
+ dc_iostream_set_rts (device->iostream, 1);
// Send the command to the dive computer.
- status = dc_serial_write (device->port, command, csize, NULL);
+ status = dc_iostream_write (device->iostream, command, csize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
}
// Clear RTS to receive the reply.
- dc_serial_set_rts (device->port, 0);
+ dc_iostream_set_rts (device->iostream, 0);
// Receive the answer of the dive computer.
- status = dc_serial_read (device->port, answer, asize, NULL);
+ status = dc_iostream_read (device->iostream, answer, asize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
diff --git a/src/usbhid.c b/src/usbhid.c
index 1b0931f..f3eb4bc 100644
--- a/src/usbhid.c
+++ b/src/usbhid.c
@@ -50,8 +50,10 @@
#endif
#include "usbhid.h"
+
#include "common-private.h"
#include "context-private.h"
+#include "iostream-private.h"
#include "platform.h"
#ifdef _WIN32
@@ -62,9 +64,17 @@ typedef pthread_mutex_t dc_mutex_t;
#define DC_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
#endif
-struct dc_usbhid_t {
- /* Library context. */
- dc_context_t *context;
+#define ISINSTANCE(device) dc_iostream_isinstance((device), &dc_usbhid_vtable)
+
+#ifdef USBHID
+static dc_status_t dc_usbhid_set_timeout (dc_iostream_t *iostream, int timeout);
+static dc_status_t dc_usbhid_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
+static dc_status_t dc_usbhid_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
+static dc_status_t dc_usbhid_close (dc_iostream_t *iostream);
+
+typedef struct dc_usbhid_t {
+ /* Base class. */
+ dc_iostream_t base;
/* Internal state. */
#if defined(USE_LIBUSB)
libusb_device_handle *handle;
@@ -76,6 +86,25 @@ struct dc_usbhid_t {
hid_device *handle;
int timeout;
#endif
+} dc_usbhid_t;
+
+static const dc_iostream_vtable_t dc_usbhid_vtable = {
+ sizeof(dc_usbhid_t),
+ dc_usbhid_set_timeout, /* set_timeout */
+ NULL, /* set_latency */
+ NULL, /* set_halfduplex */
+ NULL, /* set_break */
+ NULL, /* set_dtr */
+ NULL, /* set_rts */
+ NULL, /* get_lines */
+ NULL, /* get_received */
+ NULL, /* configure */
+ dc_usbhid_read, /* read */
+ dc_usbhid_write, /* write */
+ NULL, /* flush */
+ NULL, /* purge */
+ NULL, /* sleep */
+ dc_usbhid_close, /* close */
};
#if defined(USE_LIBUSB)
@@ -100,18 +129,19 @@ syserror(int errcode)
}
}
#endif
+#endif
static dc_status_t
usbhid_packet_close(dc_custom_io_t *io)
{
- dc_usbhid_t *usbhid = (dc_usbhid_t *)io->userdata;
+ dc_iostream_t *usbhid = (dc_iostream_t *)io->userdata;
return dc_usbhid_close(usbhid);
}
static dc_status_t
usbhid_packet_read(dc_custom_io_t *io, void* data, size_t size, size_t *actual)
{
- dc_usbhid_t *usbhid = (dc_usbhid_t *)io->userdata;
+ dc_iostream_t *usbhid = (dc_iostream_t *)io->userdata;
return dc_usbhid_read(usbhid, data, size, actual);
}
@@ -132,14 +162,14 @@ usbhid_packet_read(dc_custom_io_t *io, void* data, size_t size, size_t *actual)
static dc_status_t
usbhid_packet_write(dc_custom_io_t *io, const void* data, size_t size, size_t *actual)
{
- dc_usbhid_t *usbhid = (dc_usbhid_t *)io->userdata;
+ dc_iostream_t *usbhid = (dc_iostream_t *)io->userdata;
return dc_usbhid_write(usbhid, data, size, actual);
}
dc_status_t
dc_usbhid_custom_io (dc_context_t *context, unsigned int vid, unsigned int pid)
{
- dc_usbhid_t *usbhid;
+ dc_iostream_t *usbhid;
dc_status_t status;
static dc_custom_io_t custom = {
@@ -259,7 +289,7 @@ dc_usbhid_exit (void)
#endif
dc_status_t
-dc_usbhid_open (dc_usbhid_t **out, dc_context_t *context, unsigned int vid, unsigned int pid)
+dc_usbhid_open (dc_iostream_t **out, dc_context_t *context, unsigned int vid, unsigned int pid)
{
#ifdef USBHID
dc_status_t status = DC_STATUS_SUCCESS;
@@ -271,15 +301,12 @@ dc_usbhid_open (dc_usbhid_t **out, dc_context_t *context, unsigned int vid, unsi
INFO (context, "Open: vid=%04x, pid=%04x", vid, pid);
// Allocate memory.
- usbhid = (dc_usbhid_t *) malloc (sizeof (dc_usbhid_t));
+ usbhid = (dc_usbhid_t *) dc_iostream_allocate (context, &dc_usbhid_vtable);
if (usbhid == NULL) {
ERROR (context, "Out of memory.");
return DC_STATUS_NOMEMORY;
}
- // Library context.
- usbhid->context = context;
-
// Initialize the usb library.
status = dc_usbhid_init (context);
if (status != DC_STATUS_SUCCESS) {
@@ -422,7 +449,7 @@ dc_usbhid_open (dc_usbhid_t **out, dc_context_t *context, unsigned int vid, unsi
usbhid->timeout = -1;
#endif
- *out = usbhid;
+ *out = (dc_iostream_t *) usbhid;
return DC_STATUS_SUCCESS;
@@ -437,21 +464,19 @@ error_usb_free_list:
error_usb_exit:
dc_usbhid_exit ();
error_free:
- free (usbhid);
+ dc_iostream_deallocate ((dc_iostream_t *) usbhid);
return status;
#else
return DC_STATUS_UNSUPPORTED;
#endif
}
-dc_status_t
-dc_usbhid_close (dc_usbhid_t *usbhid)
-{
#ifdef USBHID
+static dc_status_t
+dc_usbhid_close (dc_iostream_t *abstract)
+{
dc_status_t status = DC_STATUS_SUCCESS;
-
- if (usbhid == NULL)
- return DC_STATUS_SUCCESS;
+ dc_usbhid_t *usbhid = (dc_usbhid_t *) abstract;
#if defined(USE_LIBUSB)
libusb_release_interface (usbhid->handle, usbhid->interface);
@@ -460,22 +485,14 @@ dc_usbhid_close (dc_usbhid_t *usbhid)
hid_close(usbhid->handle);
#endif
dc_usbhid_exit();
- free (usbhid);
return status;
-#else
- return DC_STATUS_UNSUPPORTED;
-#endif
}
-dc_status_t
-dc_usbhid_set_timeout (dc_usbhid_t *usbhid, int timeout)
+static dc_status_t
+dc_usbhid_set_timeout (dc_iostream_t *abstract, int timeout)
{
-#ifdef USBHID
- if (usbhid == NULL)
- return DC_STATUS_INVALIDARGS;
-
- INFO (usbhid->context, "Timeout: value=%i", timeout);
+ dc_usbhid_t *usbhid = (dc_usbhid_t *) abstract;
#if defined(USE_LIBUSB)
if (timeout < 0) {
@@ -494,27 +511,19 @@ dc_usbhid_set_timeout (dc_usbhid_t *usbhid, int timeout)
#endif
return DC_STATUS_SUCCESS;
-#else
- return DC_STATUS_UNSUPPORTED;
-#endif
}
-dc_status_t
-dc_usbhid_read (dc_usbhid_t *usbhid, void *data, size_t size, size_t *actual)
+static dc_status_t
+dc_usbhid_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
{
-#ifdef USBHID
dc_status_t status = DC_STATUS_SUCCESS;
+ dc_usbhid_t *usbhid = (dc_usbhid_t *) abstract;
int nbytes = 0;
- if (usbhid == NULL) {
- status = DC_STATUS_INVALIDARGS;
- goto out_invalidargs;
- }
-
#if defined(USE_LIBUSB)
int rc = libusb_interrupt_transfer (usbhid->handle, usbhid->endpoint_in, data, size, &nbytes, usbhid->timeout);
if (rc != LIBUSB_SUCCESS) {
- ERROR (usbhid->context, "Usb read interrupt transfer failed (%s).",
+ ERROR (abstract->context, "Usb read interrupt transfer failed (%s).",
libusb_error_name (rc));
status = syserror (rc);
goto out;
@@ -522,7 +531,7 @@ dc_usbhid_read (dc_usbhid_t *usbhid, void *data, size_t size, size_t *actual)
#elif defined(USE_HIDAPI)
nbytes = hid_read_timeout(usbhid->handle, data, size, usbhid->timeout);
if (nbytes < 0) {
- ERROR (usbhid->context, "Usb read interrupt transfer failed.");
+ ERROR (abstract->context, "Usb read interrupt transfer failed.");
status = DC_STATUS_IO;
nbytes = 0;
goto out;
@@ -530,30 +539,19 @@ dc_usbhid_read (dc_usbhid_t *usbhid, void *data, size_t size, size_t *actual)
#endif
out:
- HEXDUMP (usbhid->context, DC_LOGLEVEL_INFO, "Read", (unsigned char *) data, nbytes);
-
-out_invalidargs:
if (actual)
*actual = nbytes;
return status;
-#else
- return DC_STATUS_UNSUPPORTED;
-#endif
}
-dc_status_t
-dc_usbhid_write (dc_usbhid_t *usbhid, const void *data, size_t size, size_t *actual)
+static dc_status_t
+dc_usbhid_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual)
{
-#ifdef USBHID
dc_status_t status = DC_STATUS_SUCCESS;
+ dc_usbhid_t *usbhid = (dc_usbhid_t *) abstract;
int nbytes = 0;
- if (usbhid == NULL) {
- status = DC_STATUS_INVALIDARGS;
- goto out_invalidargs;
- }
-
if (size == 0) {
goto out;
}
@@ -571,7 +569,7 @@ dc_usbhid_write (dc_usbhid_t *usbhid, const void *data, size_t size, size_t *act
int rc = libusb_interrupt_transfer (usbhid->handle, usbhid->endpoint_out, (void *) buffer, length, &nbytes, 0);
if (rc != LIBUSB_SUCCESS) {
- ERROR (usbhid->context, "Usb write interrupt transfer failed (%s).",
+ ERROR (abstract->context, "Usb write interrupt transfer failed (%s).",
libusb_error_name (rc));
status = syserror (rc);
goto out;
@@ -583,7 +581,7 @@ dc_usbhid_write (dc_usbhid_t *usbhid, const void *data, size_t size, size_t *act
#elif defined(USE_HIDAPI)
nbytes = hid_write(usbhid->handle, data, size);
if (nbytes < 0) {
- ERROR (usbhid->context, "Usb write interrupt transfer failed.");
+ ERROR (abstract->context, "Usb write interrupt transfer failed.");
status = DC_STATUS_IO;
nbytes = 0;
goto out;
@@ -593,19 +591,14 @@ dc_usbhid_write (dc_usbhid_t *usbhid, const void *data, size_t size, size_t *act
out:
#ifdef _WIN32
if (nbytes > size) {
- WARNING (usbhid->context, "Number of bytes exceeds the buffer size (" DC_PRINTF_SIZE " > " DC_PRINTF_SIZE ")!", nbytes, size);
+ WARNING (abstract->context, "Number of bytes exceeds the buffer size (" DC_PRINTF_SIZE " > " DC_PRINTF_SIZE ")!", nbytes, size);
nbytes = size;
}
#endif
- HEXDUMP (usbhid->context, DC_LOGLEVEL_INFO, "Write", (const unsigned char *) data, nbytes);
-
-out_invalidargs:
if (actual)
*actual = nbytes;
return status;
-#else
- return DC_STATUS_UNSUPPORTED;
-#endif
}
+#endif
diff --git a/src/usbhid.h b/src/usbhid.h
index bb95a98..0b381da 100644
--- a/src/usbhid.h
+++ b/src/usbhid.h
@@ -24,20 +24,16 @@
#include
#include
+#include
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-/**
- * Opaque object representing a USB HID connection.
- */
-typedef struct dc_usbhid_t dc_usbhid_t;
-
/**
* Open a USB HID connection.
*
- * @param[out] usbhid A location to store the USB HID connection.
+ * @param[out] iostream A location to store the USB HID connection.
* @param[in] context A valid context object.
* @param[in] vid The USB Vendor ID of the device.
* @param[in] pid The USB Product ID of the device.
@@ -45,76 +41,7 @@ typedef struct dc_usbhid_t dc_usbhid_t;
* on failure.
*/
dc_status_t
-dc_usbhid_open (dc_usbhid_t **usbhid, dc_context_t *context, unsigned int vid, unsigned int pid);
-
-/**
- * Close the connection and free all resources.
- *
- * @param[in] usbhid A valid USB HID connection.
- * @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
- * on failure.
- */
-dc_status_t
-dc_usbhid_close (dc_usbhid_t *usbhid);
-
-/**
- * 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] usbhid A valid USB HID 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_usbhid_set_timeout (dc_usbhid_t *usbhid, int timeout);
-
-/**
- * Read data from the USB HID connection.
- *
- * @param[in] usbhid A valid USB HID 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_usbhid_read (dc_usbhid_t *usbhid, void *data, size_t size, size_t *actual);
-
-/**
- * Write data to the USB HID connection.
- *
- * @param[in] usbhid A valid USB HID 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_usbhid_write (dc_usbhid_t *usbhid, const void *data, size_t size, size_t *actual);
+dc_usbhid_open (dc_iostream_t **iostream, dc_context_t *context, unsigned int vid, unsigned int pid);
/* Create a dc_custom_io_t that uses usbhid for packet transfer */
dc_status_t
diff --git a/src/uwatec_aladin.c b/src/uwatec_aladin.c
index 25c9208..dc697c2 100644
--- a/src/uwatec_aladin.c
+++ b/src/uwatec_aladin.c
@@ -43,7 +43,7 @@
typedef struct uwatec_aladin_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned int timestamp;
unsigned int devtime;
dc_ticks_t systime;
@@ -86,41 +86,41 @@ uwatec_aladin_device_open (dc_device_t **out, dc_context_t *context, const char
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
device->timestamp = 0;
device->systime = (dc_ticks_t) -1;
device->devtime = 0;
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (19200 8N1).
- status = dc_serial_configure (device->port, 19200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 19200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (INFINITE).
- status = dc_serial_set_timeout (device->port, -1);
+ status = dc_iostream_set_timeout (device->iostream, -1);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Set the DTR line.
- status = dc_serial_set_dtr (device->port, 1);
+ status = dc_iostream_set_dtr (device->iostream, 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);
+ status = dc_iostream_set_rts (device->iostream, 0);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to clear the RTS line.");
goto error_close;
@@ -131,7 +131,7 @@ uwatec_aladin_device_open (dc_device_t **out, dc_context_t *context, const char
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -146,7 +146,7 @@ uwatec_aladin_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -197,7 +197,7 @@ uwatec_aladin_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
if (device_is_cancelled (abstract))
return DC_STATUS_CANCELLED;
- status = dc_serial_read (device->port, answer + i, 1, NULL);
+ status = dc_iostream_read (device->iostream, answer + i, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -218,7 +218,7 @@ 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.
- status = dc_serial_read (device->port, answer + 4, sizeof (answer) - 4, NULL);
+ status = dc_iostream_read (device->iostream, answer + 4, sizeof (answer) - 4, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Unexpected EOF in answer.");
return status;
diff --git a/src/uwatec_memomouse.c b/src/uwatec_memomouse.c
index 2f93067..90466a0 100644
--- a/src/uwatec_memomouse.c
+++ b/src/uwatec_memomouse.c
@@ -39,7 +39,7 @@
typedef struct uwatec_memomouse_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned int timestamp;
unsigned int devtime;
dc_ticks_t systime;
@@ -82,55 +82,55 @@ uwatec_memomouse_device_open (dc_device_t **out, dc_context_t *context, const ch
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
device->timestamp = 0;
device->systime = (dc_ticks_t) -1;
device->devtime = 0;
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (9600 8N1).
- status = dc_serial_configure (device->port, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 9600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (1000 ms).
- status = dc_serial_set_timeout (device->port, 1000);
+ status = dc_iostream_set_timeout (device->iostream, 1000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Clear the DTR line.
- status = dc_serial_set_dtr (device->port, 0);
+ status = dc_iostream_set_dtr (device->iostream, 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);
+ status = dc_iostream_set_rts (device->iostream, 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.
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
*out = (dc_device_t*) device;
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -145,7 +145,7 @@ uwatec_memomouse_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -180,7 +180,7 @@ uwatec_memomouse_read_packet (uwatec_memomouse_device_t *device, unsigned char d
assert (result != NULL);
// Receive the header of the package.
- status = dc_serial_read (device->port, data, 1, NULL);
+ status = dc_iostream_read (device->iostream, data, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -197,7 +197,7 @@ uwatec_memomouse_read_packet (uwatec_memomouse_device_t *device, unsigned char d
}
// Receive the remaining part of the package.
- status = dc_serial_read (device->port, data + 1, len + 1, NULL);
+ status = dc_iostream_read (device->iostream, data + 1, len + 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -234,11 +234,11 @@ uwatec_memomouse_read_packet_outer (uwatec_memomouse_device_t *device, unsigned
return rc;
// Flush the input buffer.
- dc_serial_purge (device->port, DC_DIRECTION_INPUT);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_INPUT);
// Reject the packet.
unsigned char value = NAK;
- status = dc_serial_write (device->port, &value, 1, NULL);
+ status = dc_iostream_write (device->iostream, &value, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to reject the packet.");
return status;
@@ -277,7 +277,7 @@ uwatec_memomouse_read_packet_inner (uwatec_memomouse_device_t *device, dc_buffer
// Accept the packet.
unsigned char value = ACK;
- status = dc_serial_write (device->port, &value, 1, NULL);
+ status = dc_iostream_write (device->iostream, &value, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to accept the packet.");
return status;
@@ -344,22 +344,22 @@ uwatec_memomouse_dump_internal (uwatec_memomouse_device_t *device, dc_buffer_t *
device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress);
// Waiting for greeting message.
- while (dc_serial_get_available (device->port, &available) == DC_STATUS_SUCCESS && available == 0) {
+ while (dc_iostream_get_available (device->iostream, &available) == DC_STATUS_SUCCESS && available == 0) {
if (device_is_cancelled (abstract))
return DC_STATUS_CANCELLED;
// Flush the input buffer.
- dc_serial_purge (device->port, DC_DIRECTION_INPUT);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_INPUT);
// Reject the packet.
unsigned char value = NAK;
- status = dc_serial_write (device->port, &value, 1, NULL);
+ status = dc_iostream_write (device->iostream, &value, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to reject the packet.");
return status;
}
- dc_serial_sleep (device->port, 300);
+ dc_iostream_sleep (device->iostream, 300);
}
// Read the ID string.
@@ -382,24 +382,24 @@ 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.
- dc_serial_sleep (device->port, 50);
+ dc_iostream_sleep (device->iostream, 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.
- dc_serial_purge (device->port, DC_DIRECTION_INPUT);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_INPUT);
// Send the command to the device.
- status = dc_serial_write (device->port, command, sizeof (command), NULL);
+ status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
}
// Wait for the answer (ACK).
- status = dc_serial_read (device->port, &answer, 1, NULL);
+ status = dc_iostream_read (device->iostream, &answer, 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -413,12 +413,12 @@ uwatec_memomouse_dump_internal (uwatec_memomouse_device_t *device, dc_buffer_t *
}
// Wait for the data packet.
- while (dc_serial_get_available (device->port, &available) == DC_STATUS_SUCCESS && available == 0) {
+ while (dc_iostream_get_available (device->iostream, &available) == DC_STATUS_SUCCESS && available == 0) {
if (device_is_cancelled (abstract))
return DC_STATUS_CANCELLED;
device_event_emit (&device->base, DC_EVENT_WAITING, NULL);
- dc_serial_sleep (device->port, 100);
+ dc_iostream_sleep (device->iostream, 100);
}
// Fetch the current system time.
@@ -458,10 +458,10 @@ 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).
- dc_serial_sleep (device->port, 500);
+ dc_iostream_sleep (device->iostream, 500);
// Set the DTR line.
- rc = dc_serial_set_dtr (device->port, 1);
+ rc = dc_iostream_set_dtr (device->iostream, 1);
if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to set the RTS line.");
return rc;
@@ -471,7 +471,7 @@ uwatec_memomouse_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
status = uwatec_memomouse_dump_internal (device, buffer);
// Clear the DTR line again.
- rc = dc_serial_set_dtr (device->port, 0);
+ rc = dc_iostream_set_dtr (device->iostream, 0);
if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to set the RTS line.");
return rc;
diff --git a/src/uwatec_meridian.c b/src/uwatec_meridian.c
index c32f3bc..5844c29 100644
--- a/src/uwatec_meridian.c
+++ b/src/uwatec_meridian.c
@@ -37,7 +37,7 @@
typedef struct uwatec_meridian_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned int timestamp;
unsigned int devtime;
dc_ticks_t systime;
@@ -83,7 +83,7 @@ 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.
- status = dc_serial_write (device->port, packet, csize + 12, NULL);
+ status = dc_iostream_write (device->iostream, packet, csize + 12, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
@@ -91,7 +91,7 @@ uwatec_meridian_transfer (uwatec_meridian_device_t *device, const unsigned char
// Read the echo.
unsigned char echo[sizeof(packet)];
- status = dc_serial_read (device->port, echo, csize + 12, NULL);
+ status = dc_iostream_read (device->iostream, echo, csize + 12, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the echo.");
return status;
@@ -105,7 +105,7 @@ uwatec_meridian_transfer (uwatec_meridian_device_t *device, const unsigned char
// Read the header.
unsigned char header[6];
- status = dc_serial_read (device->port, header, sizeof (header), NULL);
+ status = dc_iostream_read (device->iostream, header, sizeof (header), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the header.");
return status;
@@ -118,7 +118,7 @@ uwatec_meridian_transfer (uwatec_meridian_device_t *device, const unsigned char
}
// Read the packet.
- status = dc_serial_read (device->port, answer, asize, NULL);
+ status = dc_iostream_read (device->iostream, answer, asize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the packet.");
return status;
@@ -126,7 +126,7 @@ uwatec_meridian_transfer (uwatec_meridian_device_t *device, const unsigned char
// Read the checksum.
unsigned char csum = 0x00;
- status = dc_serial_read (device->port, &csum, sizeof (csum), NULL);
+ status = dc_iostream_read (device->iostream, &csum, sizeof (csum), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the checksum.");
return status;
@@ -199,34 +199,34 @@ uwatec_meridian_device_open (dc_device_t **out, dc_context_t *context, const cha
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
device->timestamp = 0;
device->systime = (dc_ticks_t) -1;
device->devtime = 0;
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (57600 8N1).
- status = dc_serial_configure (device->port, 57600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 57600, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (3000ms).
- status = dc_serial_set_timeout (device->port, 3000);
+ status = dc_iostream_set_timeout (device->iostream, 3000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Make sure everything is in a sane state.
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
// Perform the handshaking.
status = uwatec_meridian_handshake (device);
@@ -240,7 +240,7 @@ uwatec_meridian_device_open (dc_device_t **out, dc_context_t *context, const cha
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -255,7 +255,7 @@ uwatec_meridian_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -398,7 +398,7 @@ uwatec_meridian_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
// Read the header.
unsigned char header[5];
- status = dc_serial_read (device->port, header, sizeof (header), NULL);
+ status = dc_iostream_read (device->iostream, header, sizeof (header), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the header.");
return status;
@@ -412,7 +412,7 @@ uwatec_meridian_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
}
// Read the packet data.
- status = dc_serial_read (device->port, data + nbytes, packetsize - 1, NULL);
+ status = dc_iostream_read (device->iostream, data + nbytes, packetsize - 1, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the packet.");
return status;
@@ -420,7 +420,7 @@ uwatec_meridian_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
// Read the checksum.
unsigned char csum = 0x00;
- status = dc_serial_read (device->port, &csum, sizeof (csum), NULL);
+ status = dc_iostream_read (device->iostream, &csum, sizeof (csum), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the checksum.");
return status;
diff --git a/src/uwatec_smart.c b/src/uwatec_smart.c
index 4fd2e2d..bb67131 100644
--- a/src/uwatec_smart.c
+++ b/src/uwatec_smart.c
@@ -32,7 +32,7 @@
typedef struct uwatec_smart_device_t {
dc_device_t base;
- dc_irda_t *socket;
+ dc_iostream_t *iostream;
unsigned int address;
unsigned int timestamp;
unsigned int devtime;
@@ -88,13 +88,13 @@ uwatec_smart_transfer (uwatec_smart_device_t *device, const unsigned char comman
dc_status_t status = DC_STATUS_SUCCESS;
dc_device_t *abstract = (dc_device_t *) device;
- status = dc_irda_write (device->socket, command, csize, NULL);
+ status = dc_iostream_write (device->iostream, command, csize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
}
- status = dc_irda_read (device->socket, answer, asize, NULL);
+ status = dc_iostream_read (device->iostream, answer, asize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -158,21 +158,21 @@ uwatec_smart_device_open (dc_device_t **out, dc_context_t *context)
}
// Set the default values.
- device->socket = NULL;
+ device->iostream = NULL;
device->address = 0;
device->timestamp = 0;
device->systime = (dc_ticks_t) -1;
device->devtime = 0;
// Open the irda socket.
- status = dc_irda_open (&device->socket, context);
+ status = dc_irda_open (&device->iostream, context);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the irda socket.");
goto error_free;
}
// Discover the device.
- status = dc_irda_discover (device->socket, uwatec_smart_discovery, device);
+ status = dc_irda_discover (device->iostream, uwatec_smart_discovery, device);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to discover the device.");
goto error_close;
@@ -185,7 +185,7 @@ uwatec_smart_device_open (dc_device_t **out, dc_context_t *context)
}
// Connect the device.
- status = dc_irda_connect_lsap (device->socket, device->address, 1);
+ status = dc_irda_connect_lsap (device->iostream, device->address, 1);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to connect the device.");
goto error_close;
@@ -203,7 +203,7 @@ uwatec_smart_device_open (dc_device_t **out, dc_context_t *context)
return DC_STATUS_SUCCESS;
error_close:
- dc_irda_close (device->socket);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -218,7 +218,7 @@ uwatec_smart_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_irda_close (device->socket);
+ rc = dc_iostream_close (device->iostream);
if (status != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}
@@ -362,7 +362,7 @@ uwatec_smart_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
// Increase the packet size if more data is immediately available.
size_t available = 0;
- rc = dc_irda_get_available (device->socket, &available);
+ rc = dc_iostream_get_available (device->iostream, &available);
if (rc == DC_STATUS_SUCCESS && available > len)
len = available;
@@ -370,7 +370,7 @@ uwatec_smart_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
if (nbytes + len > length)
len = length - nbytes;
- rc = dc_irda_read (device->socket, data + nbytes, len, NULL);
+ rc = dc_iostream_read (device->iostream, data + nbytes, len, NULL);
if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return rc;
diff --git a/src/zeagle_n2ition3.c b/src/zeagle_n2ition3.c
index 3d2bb24..01b9d5e 100644
--- a/src/zeagle_n2ition3.c
+++ b/src/zeagle_n2ition3.c
@@ -46,7 +46,7 @@
typedef struct zeagle_n2ition3_device_t {
dc_device_t base;
- dc_serial_t *port;
+ dc_iostream_t *iostream;
unsigned char fingerprint[16];
} zeagle_n2ition3_device_t;
@@ -81,14 +81,14 @@ zeagle_n2ition3_packet (zeagle_n2ition3_device_t *device, const unsigned char co
return DC_STATUS_CANCELLED;
// Send the command to the device.
- status = dc_serial_write (device->port, command, csize, NULL);
+ status = dc_iostream_write (device->iostream, command, csize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
}
// Receive the answer of the device.
- status = dc_serial_read (device->port, answer, asize, NULL);
+ status = dc_iostream_read (device->iostream, answer, asize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to receive the answer.");
return status;
@@ -149,32 +149,32 @@ zeagle_n2ition3_device_open (dc_device_t **out, dc_context_t *context, const cha
}
// Set the default values.
- device->port = NULL;
+ device->iostream = NULL;
memset (device->fingerprint, 0, sizeof (device->fingerprint));
// Open the device.
- status = dc_serial_open (&device->port, context, name);
+ status = dc_serial_open (&device->iostream, context, name);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
goto error_free;
}
// Set the serial communication protocol (4800 8N1).
- status = dc_serial_configure (device->port, 4800, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
+ status = dc_iostream_configure (device->iostream, 4800, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the terminal attributes.");
goto error_close;
}
// Set the timeout for receiving data (1000 ms).
- status = dc_serial_set_timeout (device->port, 1000);
+ status = dc_iostream_set_timeout (device->iostream, 1000);
if (status != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to set the timeout.");
goto error_close;
}
// Make sure everything is in a sane state.
- dc_serial_purge (device->port, DC_DIRECTION_ALL);
+ dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
// Send the init commands.
zeagle_n2ition3_init (device);
@@ -184,7 +184,7 @@ zeagle_n2ition3_device_open (dc_device_t **out, dc_context_t *context, const cha
return DC_STATUS_SUCCESS;
error_close:
- dc_serial_close (device->port);
+ dc_iostream_close (device->iostream);
error_free:
dc_device_deallocate ((dc_device_t *) device);
return status;
@@ -199,7 +199,7 @@ zeagle_n2ition3_device_close (dc_device_t *abstract)
dc_status_t rc = DC_STATUS_SUCCESS;
// Close the device.
- rc = dc_serial_close (device->port);
+ rc = dc_iostream_close (device->iostream);
if (rc != DC_STATUS_SUCCESS) {
dc_status_set_error(&status, rc);
}