From b75095cefa71064f01e31e3180d8a3107650424b Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 24 Nov 2017 23:48:55 +0100 Subject: [PATCH 01/13] Post release version bump to 0.7.0 --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index e3abae5..9ca814b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,8 @@ # 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],[]) +m4_define([dc_version_suffix],[devel]) m4_define([dc_version],dc_version_major.dc_version_minor.dc_version_micro[]m4_ifset([dc_version_suffix],-[dc_version_suffix])) # Libtool versioning. From 3ca27995e14103f0335f1a0c07826db3694f9f69 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 11 Jan 2016 21:22:27 +0100 Subject: [PATCH 02/13] Add a new abstract I/O interface The purpose of the new I/O interface is to provide a common interface for all existing I/O implementations (serial, IrDA, bluetooth and USB HID). With a common interface the dive computer backends can more easily use different I/O implementations at runtime, without needing significant code changes. For example bluetooth enabled devices can easily switch between native bluetooth communication and serial port emulation mode. The new interface is modelled after the existing serial communication api. Implementations where some of those functions are meaningless (e.g. IrDA, bluetooth and USB), can just leave those functions unimplemented (causing the call to fail with DC_STATUS_UNSUPPORTED), or implement it as a no-op (always return DC_STATUS_SUCCESS). --- include/libdivecomputer/Makefile.am | 1 + include/libdivecomputer/iostream.h | 290 ++++++++++++++++++++++++++++ msvc/libdivecomputer.vcproj | 12 ++ src/Makefile.am | 1 + src/iostream-private.h | 86 +++++++++ src/iostream.c | 254 ++++++++++++++++++++++++ src/libdivecomputer.symbols | 16 ++ 7 files changed, 660 insertions(+) create mode 100644 include/libdivecomputer/iostream.h create mode 100644 src/iostream-private.h create mode 100644 src/iostream.c diff --git a/include/libdivecomputer/Makefile.am b/include/libdivecomputer/Makefile.am index 82ba21f..bbe7971 100644 --- a/include/libdivecomputer/Makefile.am +++ b/include/libdivecomputer/Makefile.am @@ -6,6 +6,7 @@ libdivecomputer_HEADERS = \ buffer.h \ descriptor.h \ iterator.h \ + iostream.h \ device.h \ parser.h \ datetime.h \ 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/msvc/libdivecomputer.vcproj b/msvc/libdivecomputer.vcproj index 242276a..cea0027 100644 --- a/msvc/libdivecomputer.vcproj +++ b/msvc/libdivecomputer.vcproj @@ -294,6 +294,10 @@ RelativePath="..\src\ihex.c" > + + @@ -624,6 +628,14 @@ RelativePath="..\src\ihex.h" > + + + + diff --git a/src/Makefile.am b/src/Makefile.am index 97062e1..5d99e69 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 \ 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/libdivecomputer.symbols b/src/libdivecomputer.symbols index 3b16700..daed9ef 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -33,6 +33,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 From 7cd1656d1d2090eeb9576a015b000db43c941889 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Wed, 17 Feb 2016 21:22:15 +0100 Subject: [PATCH 03/13] Port the serial code to the new I/O interface --- src/citizen_aqualand.c | 32 ++--- src/cochran_commander.c | 36 +++--- src/cressi_edy.c | 38 +++--- src/cressi_leonardo.c | 44 +++---- src/diverite_nitekq.c | 28 ++-- src/divesystem_idive.c | 28 ++-- src/hw_frog.c | 30 ++--- src/hw_ostc.c | 54 ++++---- src/hw_ostc3.c | 40 +++--- src/mares_common.c | 14 +- src/mares_common.h | 2 +- src/mares_darwin.c | 18 +-- src/mares_iconhd.c | 30 ++--- src/mares_nemo.c | 28 ++-- src/mares_puck.c | 16 +-- src/oceanic_atom2.c | 34 ++--- src/oceanic_veo250.c | 40 +++--- src/oceanic_vtpro.c | 38 +++--- src/reefnet_sensus.c | 28 ++-- src/reefnet_sensuspro.c | 32 ++--- src/reefnet_sensusultra.c | 28 ++-- src/serial.h | 260 +------------------------------------- src/serial_posix.c | 247 +++++++++++++++++------------------- src/serial_win32.c | 231 ++++++++++++++++----------------- src/shearwater_common.c | 24 ++-- src/shearwater_common.h | 2 +- src/suunto_d9.c | 32 ++--- src/suunto_eon.c | 26 ++-- src/suunto_solution.c | 42 +++--- src/suunto_vyper.c | 38 +++--- src/suunto_vyper2.c | 32 ++--- src/uwatec_aladin.c | 22 ++-- src/uwatec_memomouse.c | 56 ++++---- src/uwatec_meridian.c | 32 ++--- src/zeagle_n2ition3.c | 20 +-- 35 files changed, 705 insertions(+), 997 deletions(-) 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/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/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/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..6f0354f 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); } 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/serial.h b/src/serial.h index ac94ec8..d6620e0 100644 --- a/src/serial.h +++ b/src/serial.h @@ -24,64 +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; - -/** - * 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; - /** * Serial enumeration callback. * @@ -104,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 79fadeb..7b79ecc 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,9 +176,10 @@ 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) return DC_STATUS_INVALIDARGS; @@ -150,15 +187,12 @@ dc_serial_open (dc_serial_t **out, dc_context_t *context, const char *name) INFO (context, "Open: name=%s", name ? 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; @@ -198,29 +232,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; + 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)); } @@ -232,31 +264,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); + 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); } @@ -353,7 +378,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); } @@ -450,7 +475,7 @@ 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) { int errcode = errno; - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); return syserror (errcode); } @@ -461,7 +486,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); } @@ -473,14 +498,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 @@ -495,42 +520,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); + 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; + 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); } @@ -544,7 +564,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) @@ -554,7 +574,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 @@ -562,17 +582,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; - } - // The total timeout. int timeout = device->timeout; @@ -590,7 +606,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; } @@ -618,7 +634,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) { @@ -630,7 +646,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) { @@ -645,32 +661,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; - } - 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; } @@ -686,7 +695,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) { @@ -698,7 +707,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) { @@ -717,7 +726,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; } @@ -727,7 +736,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; } @@ -748,27 +757,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); + dc_serial_t *device = (dc_serial_t *) abstract; int flags = 0; @@ -788,93 +791,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); + 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); + 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); + 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; + 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); } @@ -884,18 +872,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); } @@ -914,14 +900,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; @@ -929,7 +910,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 c6f87f0..fb9940b 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,9 +156,10 @@ 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) return DC_STATUS_INVALIDARGS; @@ -143,15 +180,12 @@ 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; @@ -183,60 +217,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; + 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); + 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); } @@ -326,7 +351,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); } @@ -336,19 +361,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); + 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); } @@ -379,47 +401,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; + 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) { 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; - } - if (!ReadFile (device->hFile, data, size, &dwRead, NULL)) { DWORD errcode = GetLastError (); - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); status = syserror (errcode); goto out; } @@ -429,33 +443,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) { 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; - } - 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; } @@ -463,7 +470,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; } @@ -472,7 +479,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; } @@ -491,7 +498,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); } } @@ -500,22 +507,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); + dc_serial_t *device = (dc_serial_t *) abstract; DWORD flags = 0; @@ -535,48 +536,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); + 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); } } @@ -584,55 +579,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); + 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); + 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; + 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); } @@ -642,18 +630,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); } @@ -672,14 +658,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 d4b8297..68d7b46 100644 --- a/src/shearwater_common.c +++ b/src/shearwater_common.c @@ -41,34 +41,34 @@ 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."); 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); return DC_STATUS_SUCCESS; error_close: - dc_serial_close (device->port); + dc_iostream_close (device->iostream); return status; } @@ -77,7 +77,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); } @@ -153,7 +153,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; } @@ -182,7 +182,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; } @@ -200,7 +200,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; } @@ -223,7 +223,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; } @@ -242,7 +242,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/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_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_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/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/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); } From 8f17055ec49791edcc83b52adb58306de09e4399 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Wed, 17 Feb 2016 23:50:14 +0100 Subject: [PATCH 04/13] Port the IrDA code to the new I/O interface --- src/irda.c | 168 +++++++++++++++++++++------------------------ src/irda.h | 103 +++------------------------ src/uwatec_smart.c | 22 +++--- 3 files changed, 100 insertions(+), 193 deletions(-) diff --git a/src/irda.c b/src/irda.c index 1a2c38c..980fab5 100644 --- a/src/irda.c +++ b/src/irda.c @@ -50,8 +50,10 @@ #endif #include "irda.h" + #include "common-private.h" #include "context-private.h" +#include "iostream-private.h" #include "array.h" #include "platform.h" @@ -83,17 +85,44 @@ typedef int s_errcode_t; #define S_CLOSE close #endif -struct dc_irda_t { - dc_context_t *context; +#define ISINSTANCE(device) dc_iostream_isinstance((device), &dc_irda_vtable) + +#ifdef IRDA +static dc_status_t dc_irda_set_timeout (dc_iostream_t *iostream, int timeout); +static dc_status_t dc_irda_get_available (dc_iostream_t *iostream, size_t *value); +static dc_status_t dc_irda_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual); +static dc_status_t dc_irda_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual); +static dc_status_t dc_irda_close (dc_iostream_t *iostream); + +typedef struct dc_irda_t { + dc_iostream_t base; #ifdef _WIN32 SOCKET fd; #else int fd; #endif int timeout; +} dc_irda_t; + +static const dc_iostream_vtable_t dc_irda_vtable = { + sizeof(dc_irda_t), + dc_irda_set_timeout, /* set_timeout */ + NULL, /* set_latency */ + NULL, /* set_halfduplex */ + NULL, /* set_break */ + NULL, /* set_dtr */ + NULL, /* set_rts */ + NULL, /* get_lines */ + dc_irda_get_available, /* get_received */ + NULL, /* configure */ + dc_irda_read, /* read */ + dc_irda_write, /* write */ + NULL, /* flush */ + NULL, /* purge */ + NULL, /* sleep */ + dc_irda_close, /* close */ }; -#ifdef IRDA static dc_status_t syserror(s_errcode_t errcode) { @@ -113,7 +142,7 @@ syserror(s_errcode_t errcode) #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; @@ -123,15 +152,12 @@ dc_irda_open (dc_irda_t **out, dc_context_t *context) return DC_STATUS_INVALIDARGS; // Allocate memory. - device = (dc_irda_t *) malloc (sizeof (dc_irda_t)); + device = (dc_irda_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; @@ -166,7 +192,7 @@ dc_irda_open (dc_irda_t **out, dc_context_t *context) goto error_wsacleanup; } - *out = device; + *out = (dc_iostream_t *) device; return DC_STATUS_SUCCESS; @@ -175,21 +201,19 @@ error_wsacleanup: 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 +static dc_status_t +dc_irda_close (dc_iostream_t *abstract) +{ dc_status_t status = DC_STATUS_SUCCESS; - - if (device == NULL) - return DC_STATUS_SUCCESS; + dc_irda_t *device = (dc_irda_t *) abstract; // Terminate all send and receive operations. shutdown (device->fd, 0); @@ -197,7 +221,7 @@ dc_irda_close (dc_irda_t *device) // Close the socket. if (S_CLOSE (device->fd) != 0) { s_errcode_t errcode = S_ERRNO; - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); dc_status_set_error(&status, syserror(errcode)); } @@ -205,37 +229,24 @@ dc_irda_close (dc_irda_t *device) // Terminate the winsock dll. if (WSACleanup () != 0) { s_errcode_t errcode = S_ERRNO; - SYSERROR (device->context, errcode); + SYSERROR (abstract->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) +static dc_status_t +dc_irda_set_timeout (dc_iostream_t *abstract, int timeout) { -#ifdef IRDA - if (device == NULL) - return DC_STATUS_INVALIDARGS; - - INFO (device->context, "Timeout: value=%i", timeout); + dc_irda_t *device = (dc_irda_t *) abstract; device->timeout = timeout; return DC_STATUS_SUCCESS; -#else - return DC_STATUS_UNSUPPORTED; -#endif } - +#endif #define DISCOVER_MAX_DEVICES 16 // Maximum number of devices. #define DISCOVER_MAX_RETRIES 4 // Maximum number of retries. @@ -249,10 +260,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_irda_t *device = (dc_irda_t *) abstract; + + if (!ISINSTANCE (abstract)) return DC_STATUS_INVALIDARGS; unsigned char data[DISCOVER_BUFSIZE] = {0}; @@ -280,7 +293,7 @@ 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); + SYSERROR (abstract->context, errcode); return syserror(errcode); } } @@ -316,7 +329,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 +344,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_irda_t *device = (dc_irda_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; @@ -362,7 +377,7 @@ dc_irda_connect_name (dc_irda_t *device, unsigned int address, const char *name) if (connect (device->fd, (struct sockaddr *) &peer, sizeof (peer)) != 0) { s_errcode_t errcode = S_ERRNO; - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); return syserror(errcode); } @@ -373,13 +388,15 @@ dc_irda_connect_name (dc_irda_t *device, unsigned int address, const char *name) } 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_irda_t *device = (dc_irda_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; @@ -399,7 +416,7 @@ dc_irda_connect_lsap (dc_irda_t *device, unsigned int address, unsigned int lsap if (connect (device->fd, (struct sockaddr *) &peer, sizeof (peer)) != 0) { s_errcode_t errcode = S_ERRNO; - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); return syserror(errcode); } @@ -409,12 +426,11 @@ dc_irda_connect_lsap (dc_irda_t *device, unsigned int address, unsigned int lsap #endif } -dc_status_t -dc_irda_get_available (dc_irda_t *device, size_t *value) -{ #ifdef IRDA - if (device == NULL) - return DC_STATUS_INVALIDARGS; +static dc_status_t +dc_irda_get_available (dc_iostream_t *abstract, size_t *value) +{ + dc_irda_t *device = (dc_irda_t *) abstract; #ifdef _WIN32 unsigned long bytes = 0; @@ -424,7 +440,7 @@ dc_irda_get_available (dc_irda_t *device, size_t *value) if (S_IOCTL (device->fd, FIONREAD, &bytes) != 0) { s_errcode_t errcode = S_ERRNO; - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); return syserror(errcode); } @@ -432,23 +448,15 @@ dc_irda_get_available (dc_irda_t *device, size_t *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) +static dc_status_t +dc_irda_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual) { -#ifdef IRDA dc_status_t status = DC_STATUS_SUCCESS; + dc_irda_t *device = (dc_irda_t *) abstract; size_t nbytes = 0; - if (device == NULL) { - status = DC_STATUS_INVALIDARGS; - goto out_invalidargs; - } - while (nbytes < size) { fd_set fds; FD_ZERO (&fds); @@ -467,7 +475,7 @@ dc_irda_read (dc_irda_t *device, void *data, size_t size, size_t *actual) s_errcode_t errcode = S_ERRNO; if (errcode == S_EINTR) continue; // Retry. - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); status = syserror(errcode); goto out; } else if (rc == 0) { @@ -479,7 +487,7 @@ dc_irda_read (dc_irda_t *device, void *data, size_t size, size_t *actual) s_errcode_t errcode = S_ERRNO; if (errcode == S_EINTR || errcode == S_EAGAIN) continue; // Retry. - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); status = syserror(errcode); goto out; } else if (n == 0) { @@ -494,30 +502,19 @@ dc_irda_read (dc_irda_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; -#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) +static dc_status_t +dc_irda_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual) { -#ifdef IRDA dc_status_t status = DC_STATUS_SUCCESS; + dc_irda_t *device = (dc_irda_t *) abstract; size_t nbytes = 0; - if (device == NULL) { - status = DC_STATUS_INVALIDARGS; - goto out_invalidargs; - } - while (nbytes < size) { fd_set fds; FD_ZERO (&fds); @@ -528,7 +525,7 @@ dc_irda_write (dc_irda_t *device, const void *data, size_t size, size_t *actual) s_errcode_t errcode = S_ERRNO; if (errcode == S_EINTR) continue; // Retry. - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); status = syserror(errcode); goto out; } else if (rc == 0) { @@ -540,7 +537,7 @@ dc_irda_write (dc_irda_t *device, const void *data, size_t size, size_t *actual) s_errcode_t errcode = S_ERRNO; if (errcode == S_EINTR || errcode == S_EAGAIN) continue; // Retry. - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); status = syserror(errcode); goto out; } else if (n == 0) { @@ -555,14 +552,9 @@ dc_irda_write (dc_irda_t *device, const void *data, size_t size, size_t *actual) } out: - HEXDUMP (device->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/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/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; From 300ef5257b4b892668b9cda193f83f45d92374b1 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Wed, 3 May 2017 23:12:06 +0200 Subject: [PATCH 05/13] Port the bluetooth code to the new I/O interface --- src/bluetooth.c | 171 ++++++++++++++++++++++-------------------------- src/bluetooth.h | 99 ++-------------------------- 2 files changed, 87 insertions(+), 183 deletions(-) diff --git a/src/bluetooth.c b/src/bluetooth.c index 01a3e96..40fa7a6 100644 --- a/src/bluetooth.c +++ b/src/bluetooth.c @@ -51,8 +51,10 @@ #endif #include "bluetooth.h" + #include "common-private.h" #include "context-private.h" +#include "iostream-private.h" #ifdef _WIN32 typedef int s_ssize_t; @@ -93,17 +95,44 @@ typedef int s_errcode_t; #define MAX_DEVICES 255 #define MAX_PERIODS 8 -struct dc_bluetooth_t { - dc_context_t *context; +#define ISINSTANCE(device) dc_iostream_isinstance((device), &dc_bluetooth_vtable) + +#ifdef BLUETOOTH +static dc_status_t dc_bluetooth_set_timeout (dc_iostream_t *iostream, int timeout); +static dc_status_t dc_bluetooth_get_available (dc_iostream_t *iostream, size_t *value); +static dc_status_t dc_bluetooth_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual); +static dc_status_t dc_bluetooth_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual); +static dc_status_t dc_bluetooth_close (dc_iostream_t *iostream); + +typedef struct dc_bluetooth_t { + dc_iostream_t base; #ifdef _WIN32 SOCKET fd; #else int fd; #endif int timeout; +} dc_bluetooth_t; + +static const dc_iostream_vtable_t dc_bluetooth_vtable = { + sizeof(dc_bluetooth_t), + dc_bluetooth_set_timeout, /* set_timeout */ + NULL, /* set_latency */ + NULL, /* set_halfduplex */ + NULL, /* set_break */ + NULL, /* set_dtr */ + NULL, /* set_rts */ + NULL, /* get_lines */ + dc_bluetooth_get_available, /* get_received */ + NULL, /* configure */ + dc_bluetooth_read, /* read */ + dc_bluetooth_write, /* write */ + NULL, /* flush */ + NULL, /* purge */ + NULL, /* sleep */ + dc_bluetooth_close, /* close */ }; -#ifdef BLUETOOTH static dc_status_t syserror(s_errcode_t errcode) { @@ -120,7 +149,6 @@ syserror(s_errcode_t errcode) return DC_STATUS_IO; } } -#endif #ifdef HAVE_BLUEZ static dc_bluetooth_address_t @@ -147,9 +175,10 @@ 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; @@ -159,15 +188,12 @@ dc_bluetooth_open (dc_bluetooth_t **out, dc_context_t *context) return DC_STATUS_INVALIDARGS; // Allocate memory. - device = (dc_bluetooth_t *) malloc (sizeof (dc_bluetooth_t)); + device = (dc_bluetooth_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; @@ -206,7 +232,7 @@ dc_bluetooth_open (dc_bluetooth_t **out, dc_context_t *context) goto error_wsacleanup; } - *out = device; + *out = (dc_iostream_t *) device; return DC_STATUS_SUCCESS; @@ -215,21 +241,19 @@ error_wsacleanup: 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_bluetooth_close (dc_bluetooth_t *device) -{ #ifdef BLUETOOTH +static dc_status_t +dc_bluetooth_close (dc_iostream_t *abstract) +{ dc_status_t status = DC_STATUS_SUCCESS; - - if (device == NULL) - return DC_STATUS_SUCCESS; + dc_bluetooth_t *device = (dc_bluetooth_t *) abstract; // Terminate all send and receive operations. shutdown (device->fd, 0); @@ -237,7 +261,7 @@ dc_bluetooth_close (dc_bluetooth_t *device) // Close the socket. if (S_CLOSE (device->fd) != 0) { s_errcode_t errcode = S_ERRNO; - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); dc_status_set_error(&status, syserror(errcode)); } @@ -245,44 +269,32 @@ dc_bluetooth_close (dc_bluetooth_t *device) // Terminate the winsock dll. if (WSACleanup () != 0) { s_errcode_t errcode = S_ERRNO; - SYSERROR (device->context, errcode); + SYSERROR (abstract->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) +static dc_status_t +dc_bluetooth_set_timeout (dc_iostream_t *abstract, int timeout) { -#ifdef BLUETOOTH - if (device == NULL) - return DC_STATUS_INVALIDARGS; - - INFO (device->context, "Timeout: value=%i", timeout); + dc_bluetooth_t *device = (dc_bluetooth_t *) abstract; device->timeout = timeout; return DC_STATUS_SUCCESS; -#else - return DC_STATUS_UNSUPPORTED; -#endif } +#endif dc_status_t -dc_bluetooth_discover (dc_bluetooth_t *device, dc_bluetooth_callback_t callback, void *userdata) +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) + if (!ISINSTANCE (abstract)) return DC_STATUS_INVALIDARGS; #ifdef _WIN32 @@ -299,7 +311,7 @@ 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); + SYSERROR (abstract->context, errcode); status = syserror(errcode); } goto error_exit; @@ -319,7 +331,7 @@ 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); + SYSERROR (abstract->context, errcode); status = syserror(errcode); goto error_close; } @@ -327,7 +339,7 @@ dc_bluetooth_discover (dc_bluetooth_t *device, dc_bluetooth_callback_t callback, 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 +348,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,7 +361,7 @@ error_close: int dev = hci_get_route (NULL); if (dev < 0) { s_errcode_t errcode = S_ERRNO; - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); status = syserror(errcode); goto error_exit; } @@ -358,7 +370,7 @@ error_close: int fd = hci_open_dev (dev); if (fd < 0) { s_errcode_t errcode = S_ERRNO; - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); status = syserror(errcode); goto error_exit; } @@ -367,7 +379,7 @@ 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); + SYSERROR (abstract->context, errcode); status = syserror(errcode); goto error_close; } @@ -378,7 +390,7 @@ 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); + SYSERROR (abstract->context, errcode); status = syserror(errcode); goto error_free; } @@ -393,7 +405,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 +424,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_bluetooth_t *device = (dc_bluetooth_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; @@ -435,7 +449,7 @@ dc_bluetooth_connect (dc_bluetooth_t *device, dc_bluetooth_address_t address, un if (connect (device->fd, (struct sockaddr *) &sa, sizeof (sa)) != 0) { s_errcode_t errcode = S_ERRNO; - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); return syserror(errcode); } @@ -445,12 +459,11 @@ dc_bluetooth_connect (dc_bluetooth_t *device, dc_bluetooth_address_t address, un #endif } -dc_status_t -dc_bluetooth_get_available (dc_bluetooth_t *device, size_t *value) -{ #ifdef BLUETOOTH - if (device == NULL) - return DC_STATUS_INVALIDARGS; +static dc_status_t +dc_bluetooth_get_available (dc_iostream_t *abstract, size_t *value) +{ + dc_bluetooth_t *device = (dc_bluetooth_t *) abstract; #ifdef _WIN32 unsigned long bytes = 0; @@ -460,7 +473,7 @@ dc_bluetooth_get_available (dc_bluetooth_t *device, size_t *value) if (S_IOCTL (device->fd, FIONREAD, &bytes) != 0) { s_errcode_t errcode = S_ERRNO; - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); return syserror(errcode); } @@ -468,23 +481,15 @@ dc_bluetooth_get_available (dc_bluetooth_t *device, size_t *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) +static dc_status_t +dc_bluetooth_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual) { -#ifdef BLUETOOTH dc_status_t status = DC_STATUS_SUCCESS; + dc_bluetooth_t *device = (dc_bluetooth_t *) abstract; size_t nbytes = 0; - if (device == NULL) { - status = DC_STATUS_INVALIDARGS; - goto out_invalidargs; - } - while (nbytes < size) { fd_set fds; FD_ZERO (&fds); @@ -503,7 +508,7 @@ dc_bluetooth_read (dc_bluetooth_t *device, void *data, size_t size, size_t *actu s_errcode_t errcode = S_ERRNO; if (errcode == S_EINTR) continue; // Retry. - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); status = syserror(errcode); goto out; } else if (rc == 0) { @@ -515,7 +520,7 @@ dc_bluetooth_read (dc_bluetooth_t *device, void *data, size_t size, size_t *actu s_errcode_t errcode = S_ERRNO; if (errcode == S_EINTR || errcode == S_EAGAIN) continue; // Retry. - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); status = syserror(errcode); goto out; } else if (n == 0) { @@ -530,30 +535,19 @@ dc_bluetooth_read (dc_bluetooth_t *device, void *data, size_t size, size_t *actu } 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) +static dc_status_t +dc_bluetooth_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual) { -#ifdef BLUETOOTH dc_status_t status = DC_STATUS_SUCCESS; + dc_bluetooth_t *device = (dc_bluetooth_t *) abstract; size_t nbytes = 0; - if (device == NULL) { - status = DC_STATUS_INVALIDARGS; - goto out_invalidargs; - } - while (nbytes < size) { fd_set fds; FD_ZERO (&fds); @@ -564,7 +558,7 @@ dc_bluetooth_write (dc_bluetooth_t *device, const void *data, size_t size, size_ s_errcode_t errcode = S_ERRNO; if (errcode == S_EINTR) continue; // Retry. - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); status = syserror(errcode); goto out; } else if (rc == 0) { @@ -576,7 +570,7 @@ dc_bluetooth_write (dc_bluetooth_t *device, const void *data, size_t size, size_ s_errcode_t errcode = S_ERRNO; if (errcode == S_EINTR || errcode == S_EAGAIN) continue; // Retry. - SYSERROR (device->context, errcode); + SYSERROR (abstract->context, errcode); status = syserror(errcode); goto out; } else if (n == 0) { @@ -591,14 +585,9 @@ dc_bluetooth_write (dc_bluetooth_t *device, const void *data, size_t size, size_ } out: - HEXDUMP (device->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/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 } From cf9626efc35456b74d2d6c16d93a224dad65ceba Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Wed, 3 May 2017 23:38:17 +0200 Subject: [PATCH 06/13] Port the USB HID code to the new I/O interface --- src/suunto_eonsteel.c | 18 +++---- src/usbhid.c | 119 ++++++++++++++++++++---------------------- src/usbhid.h | 79 ++-------------------------- src/uwatec_g2.c | 14 ++--- 4 files changed, 75 insertions(+), 155 deletions(-) diff --git a/src/suunto_eonsteel.c b/src/suunto_eonsteel.c index cd7bc79..d82da44 100644 --- a/src/suunto_eonsteel.c +++ b/src/suunto_eonsteel.c @@ -35,7 +35,7 @@ typedef struct suunto_eonsteel_device_t { dc_device_t base; - dc_usbhid_t *usbhid; + dc_iostream_t *iostream; unsigned int model; unsigned int magic; unsigned short seq; @@ -141,7 +141,7 @@ static int receive_packet(suunto_eonsteel_device_t *eon, unsigned char *buffer, size_t transferred = 0; int len; - rc = dc_usbhid_read(eon->usbhid, buf, PACKET_SIZE, &transferred); + rc = dc_iostream_read(eon->iostream, buf, PACKET_SIZE, &transferred); if (rc != DC_STATUS_SUCCESS) { ERROR(eon->base.context, "read interrupt transfer failed"); return -1; @@ -207,7 +207,7 @@ static int send_cmd(suunto_eonsteel_device_t *eon, memcpy(buf+14, buffer, len); } - rc = dc_usbhid_write(eon->usbhid, buf, sizeof(buf), &transferred); + rc = dc_iostream_write(eon->iostream, buf, sizeof(buf), &transferred); if (rc != DC_STATUS_SUCCESS) { ERROR(eon->base.context, "write interrupt transfer failed"); return -1; @@ -523,20 +523,20 @@ static int initialize_eonsteel(suunto_eonsteel_device_t *eon) unsigned char buf[64]; struct eon_hdr hdr; - dc_usbhid_set_timeout(eon->usbhid, 10); + dc_iostream_set_timeout(eon->iostream, 10); /* Get rid of any pending stale input first */ for (;;) { size_t transferred = 0; - dc_status_t rc = dc_usbhid_read(eon->usbhid, buf, sizeof(buf), &transferred); + dc_status_t rc = dc_iostream_read(eon->iostream, buf, sizeof(buf), &transferred); if (rc != DC_STATUS_SUCCESS) break; if (!transferred) break; } - dc_usbhid_set_timeout(eon->usbhid, 5000); + dc_iostream_set_timeout(eon->iostream, 5000); if (send_cmd(eon, CMD_INIT, sizeof(init), init)) { ERROR(eon->base.context, "Failed to send initialization command"); @@ -580,7 +580,7 @@ suunto_eonsteel_device_open(dc_device_t **out, dc_context_t *context, unsigned i } else { pid = 0x0030; } - status = dc_usbhid_open(&eon->usbhid, context, vid, pid); + status = dc_usbhid_open(&eon->iostream, context, vid, pid); if (status != DC_STATUS_SUCCESS) { ERROR(context, "unable to open device"); goto error_free; @@ -597,7 +597,7 @@ suunto_eonsteel_device_open(dc_device_t **out, dc_context_t *context, unsigned i return DC_STATUS_SUCCESS; error_close: - dc_usbhid_close(eon->usbhid); + dc_iostream_close(eon->iostream); error_free: free(eon); return status; @@ -771,7 +771,7 @@ suunto_eonsteel_device_close(dc_device_t *abstract) { suunto_eonsteel_device_t *eon = (suunto_eonsteel_device_t *) abstract; - dc_usbhid_close(eon->usbhid); + dc_iostream_close(eon->iostream); return DC_STATUS_SUCCESS; } diff --git a/src/usbhid.c b/src/usbhid.c index 0dff237..c9435c8 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,6 +129,7 @@ syserror(int errcode) } } #endif +#endif #ifdef USBHID static dc_mutex_t g_usbhid_mutex = DC_MUTEX_INIT; @@ -184,7 +214,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; @@ -196,15 +226,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) { @@ -347,7 +374,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; @@ -362,21 +389,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); @@ -385,22 +410,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) { @@ -419,27 +436,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; @@ -447,7 +456,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; @@ -455,30 +464,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; } @@ -496,7 +494,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; @@ -508,7 +506,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; @@ -518,19 +516,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 65d98c1..1e85f0a 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); #ifdef __cplusplus } diff --git a/src/uwatec_g2.c b/src/uwatec_g2.c index 5f62f4b..5031055 100644 --- a/src/uwatec_g2.c +++ b/src/uwatec_g2.c @@ -39,7 +39,7 @@ typedef struct uwatec_g2_device_t { dc_device_t base; - dc_usbhid_t *usbhid; + dc_iostream_t *iostream; unsigned int timestamp; unsigned int devtime; dc_ticks_t systime; @@ -74,7 +74,7 @@ receive_data (uwatec_g2_device_t *device, dc_event_progress_t *progress, unsigne dc_status_t rc = DC_STATUS_SUCCESS; unsigned int len = 0; - rc = dc_usbhid_read (device->usbhid, buf, sizeof(buf), &transferred); + rc = dc_iostream_read (device->iostream, buf, sizeof(buf), &transferred); if (rc != DC_STATUS_SUCCESS) { ERROR (device->base.context, "read interrupt transfer failed"); return rc; @@ -126,7 +126,7 @@ uwatec_g2_transfer (uwatec_g2_device_t *device, const unsigned char command[], u buf[1] = csize; memcpy(buf + 2, command, csize); memset(buf + 2 + csize, 0, sizeof(buf) - (csize + 2)); - status = dc_usbhid_write (device->usbhid, buf, sizeof(buf), &transferred); + status = dc_iostream_write (device->iostream, buf, sizeof(buf), &transferred); if (status != DC_STATUS_SUCCESS) { ERROR (device->base.context, "Failed to send the command."); return status; @@ -196,7 +196,7 @@ uwatec_g2_device_open (dc_device_t **out, dc_context_t *context, unsigned int mo } // Set the default values. - device->usbhid = NULL; + device->iostream = NULL; device->timestamp = 0; device->systime = (dc_ticks_t) -1; device->devtime = 0; @@ -210,7 +210,7 @@ uwatec_g2_device_open (dc_device_t **out, dc_context_t *context, unsigned int mo vid = 0x2e6c; pid = 0x3201; } - status = dc_usbhid_open (&device->usbhid, context, vid, pid); + status = dc_usbhid_open (&device->iostream, context, vid, pid); if (status != DC_STATUS_SUCCESS) { ERROR (context, "Failed to open USB device"); goto error_free; @@ -228,7 +228,7 @@ uwatec_g2_device_open (dc_device_t **out, dc_context_t *context, unsigned int mo return DC_STATUS_SUCCESS; error_close: - dc_usbhid_close (device->usbhid); + dc_iostream_close (device->iostream); error_free: dc_device_deallocate ((dc_device_t *) device); return status; @@ -243,7 +243,7 @@ uwatec_g2_device_close (dc_device_t *abstract) dc_status_t rc = DC_STATUS_SUCCESS; // Close the device. - rc = dc_usbhid_close (device->usbhid); + rc = dc_iostream_close (device->iostream); if (status != DC_STATUS_SUCCESS) { dc_status_set_error(&status, rc); } From 283eaa1ca6dbce8e2ee73340fb84b70bb4f96983 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 9 Jun 2017 21:13:18 +0200 Subject: [PATCH 07/13] Add support for a custom I/O implementation Wih the custom I/O implementation, an application can use its own low-level I/O layer instead of using one of the built-in ones. The application only needs to provide a set of callback functions, and libdivecomputer will wrap them into a I/O stream. --- msvc/libdivecomputer.vcproj | 8 ++ src/Makefile.am | 1 + src/custom.c | 263 ++++++++++++++++++++++++++++++++++++ src/custom.h | 67 +++++++++ 4 files changed, 339 insertions(+) create mode 100644 src/custom.c create mode 100644 src/custom.h diff --git a/msvc/libdivecomputer.vcproj b/msvc/libdivecomputer.vcproj index cea0027..ee31af8 100644 --- a/msvc/libdivecomputer.vcproj +++ b/msvc/libdivecomputer.vcproj @@ -246,6 +246,10 @@ RelativePath="..\src\cressi_leonardo_parser.c" > + + @@ -576,6 +580,10 @@ RelativePath="..\src\cressi_leonardo.h" > + + diff --git a/src/Makefile.am b/src/Makefile.am index 5d99e69..24ede8c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -81,6 +81,7 @@ endif 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 if OS_WIN32 libdivecomputer_la_SOURCES += libdivecomputer.rc 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 */ From 823303980ef86a0c044edaa83b6ba3b8956a43ed Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 7 Sep 2017 22:17:03 +0200 Subject: [PATCH 08/13] Move the socket code to a common file A large part of the irda and bluetooth code is the Windows and BSD socket code. Moving this code to a common file reduces code duplication. --- msvc/libdivecomputer.vcproj | 8 + src/Makefile.am | 1 + src/bluetooth.c | 324 +++------------------------------ src/irda.c | 345 ++++-------------------------------- src/socket.c | 295 ++++++++++++++++++++++++++++++ src/socket.h | 119 +++++++++++++ 6 files changed, 475 insertions(+), 617 deletions(-) create mode 100644 src/socket.c create mode 100644 src/socket.h diff --git a/msvc/libdivecomputer.vcproj b/msvc/libdivecomputer.vcproj index ee31af8..c54c3d7 100644 --- a/msvc/libdivecomputer.vcproj +++ b/msvc/libdivecomputer.vcproj @@ -426,6 +426,10 @@ RelativePath="..\src\shearwater_predator_parser.c" > + + @@ -768,6 +772,10 @@ RelativePath="..\src\shearwater_predator.h" > + + diff --git a/src/Makefile.am b/src/Makefile.am index 24ede8c..586b89b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -78,6 +78,7 @@ 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 diff --git a/src/bluetooth.c b/src/bluetooth.c index 40fa7a6..3399cd2 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 @@ -56,34 +48,6 @@ #include "context-private.h" #include "iostream-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 - #ifdef _WIN32 #define DC_ADDRESS_FORMAT "%012I64X" #else @@ -98,58 +62,25 @@ typedef int s_errcode_t; #define ISINSTANCE(device) dc_iostream_isinstance((device), &dc_bluetooth_vtable) #ifdef BLUETOOTH -static dc_status_t dc_bluetooth_set_timeout (dc_iostream_t *iostream, int timeout); -static dc_status_t dc_bluetooth_get_available (dc_iostream_t *iostream, size_t *value); -static dc_status_t dc_bluetooth_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual); -static dc_status_t dc_bluetooth_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual); -static dc_status_t dc_bluetooth_close (dc_iostream_t *iostream); - -typedef struct dc_bluetooth_t { - dc_iostream_t base; -#ifdef _WIN32 - SOCKET fd; -#else - int fd; -#endif - int timeout; -} dc_bluetooth_t; - static const dc_iostream_vtable_t dc_bluetooth_vtable = { - sizeof(dc_bluetooth_t), - dc_bluetooth_set_timeout, /* set_timeout */ + sizeof(dc_socket_t), + dc_socket_set_timeout, /* set_timeout */ NULL, /* set_latency */ NULL, /* set_halfduplex */ NULL, /* set_break */ NULL, /* set_dtr */ NULL, /* set_rts */ NULL, /* get_lines */ - dc_bluetooth_get_available, /* get_received */ + dc_socket_get_available, /* get_received */ NULL, /* configure */ - dc_bluetooth_read, /* read */ - dc_bluetooth_write, /* write */ + dc_socket_read, /* read */ + dc_socket_write, /* write */ NULL, /* flush */ NULL, /* purge */ NULL, /* sleep */ - dc_bluetooth_close, /* close */ + dc_socket_close, /* close */ }; -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; - } -} - #ifdef HAVE_BLUEZ static dc_bluetooth_address_t dc_address_get (const bdaddr_t *ba) @@ -182,65 +113,33 @@ 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 *) dc_iostream_allocate (context, &dc_bluetooth_vtable); + device = (dc_socket_t *) dc_iostream_allocate (context, &dc_bluetooth_vtable); if (device == NULL) { SYSERROR (context, S_ENOMEM); return DC_STATUS_NOMEMORY; } - // 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; - 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); + status = dc_socket_open (&device->base, AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); #else - device->fd = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + status = dc_socket_open (&device->base, 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; + if (status != DC_STATUS_SUCCESS) { + goto error_free; } *out = (dc_iostream_t *) device; return DC_STATUS_SUCCESS; -error_wsacleanup: -#ifdef _WIN32 - WSACleanup (); error_free: -#endif dc_iostream_deallocate ((dc_iostream_t *) device); return status; #else @@ -248,46 +147,6 @@ error_free: #endif } -#ifdef BLUETOOTH -static dc_status_t -dc_bluetooth_close (dc_iostream_t *abstract) -{ - dc_status_t status = DC_STATUS_SUCCESS; - dc_bluetooth_t *device = (dc_bluetooth_t *) abstract; - - // 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 (abstract->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 (abstract->context, errcode); - dc_status_set_error(&status, syserror(errcode)); - } -#endif - - return status; -} - -static dc_status_t -dc_bluetooth_set_timeout (dc_iostream_t *abstract, int timeout) -{ - dc_bluetooth_t *device = (dc_bluetooth_t *) abstract; - - device->timeout = timeout; - - return DC_STATUS_SUCCESS; -} -#endif - dc_status_t dc_bluetooth_discover (dc_iostream_t *abstract, dc_bluetooth_callback_t callback, void *userdata) { @@ -312,7 +171,7 @@ dc_bluetooth_discover (dc_iostream_t *abstract, dc_bluetooth_callback_t callback status = DC_STATUS_SUCCESS; } else { SYSERROR (abstract->context, errcode); - status = syserror(errcode); + status = dc_socket_syserror(errcode); } goto error_exit; } @@ -332,7 +191,7 @@ dc_bluetooth_discover (dc_iostream_t *abstract, dc_bluetooth_callback_t callback break; // No more results. } SYSERROR (abstract->context, errcode); - status = syserror(errcode); + status = dc_socket_syserror(errcode); goto error_close; } @@ -362,7 +221,7 @@ error_close: if (dev < 0) { s_errcode_t errcode = S_ERRNO; SYSERROR (abstract->context, errcode); - status = syserror(errcode); + status = dc_socket_syserror(errcode); goto error_exit; } @@ -371,7 +230,7 @@ error_close: if (fd < 0) { s_errcode_t errcode = S_ERRNO; SYSERROR (abstract->context, errcode); - status = syserror(errcode); + status = dc_socket_syserror(errcode); goto error_exit; } @@ -380,7 +239,7 @@ error_close: if (devices == NULL) { s_errcode_t errcode = S_ERRNO; SYSERROR (abstract->context, errcode); - status = syserror(errcode); + status = dc_socket_syserror(errcode); goto error_close; } @@ -391,7 +250,7 @@ error_close: if (ndevices < 0) { s_errcode_t errcode = S_ERRNO; SYSERROR (abstract->context, errcode); - status = syserror(errcode); + status = dc_socket_syserror(errcode); goto error_free; } @@ -427,7 +286,7 @@ dc_status_t dc_bluetooth_connect (dc_iostream_t *abstract, dc_bluetooth_address_t address, unsigned int port) { #ifdef BLUETOOTH - dc_bluetooth_t *device = (dc_bluetooth_t *) abstract; + dc_socket_t *device = (dc_socket_t *) abstract; if (!ISINSTANCE (abstract)) return DC_STATUS_INVALIDARGS; @@ -447,147 +306,8 @@ dc_bluetooth_connect (dc_iostream_t *abstract, dc_bluetooth_address_t address, u 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 (abstract->context, errcode); - return syserror(errcode); - } - - return DC_STATUS_SUCCESS; + return dc_socket_connect (&device->base, (struct sockaddr *) &sa, sizeof (sa)); #else return DC_STATUS_UNSUPPORTED; #endif } - -#ifdef BLUETOOTH -static dc_status_t -dc_bluetooth_get_available (dc_iostream_t *abstract, size_t *value) -{ - dc_bluetooth_t *device = (dc_bluetooth_t *) abstract; - -#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 (abstract->context, errcode); - return syserror(errcode); - } - - if (value) - *value = bytes; - - return DC_STATUS_SUCCESS; -} - -static dc_status_t -dc_bluetooth_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual) -{ - dc_status_t status = DC_STATUS_SUCCESS; - dc_bluetooth_t *device = (dc_bluetooth_t *) abstract; - size_t nbytes = 0; - - 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 (abstract->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 (abstract->context, errcode); - status = 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; -} - -static dc_status_t -dc_bluetooth_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual) -{ - dc_status_t status = DC_STATUS_SUCCESS; - dc_bluetooth_t *device = (dc_bluetooth_t *) abstract; - size_t nbytes = 0; - - 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 (abstract->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 (abstract->context, errcode); - status = 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; -} -#endif diff --git a/src/irda.c b/src/irda.c index 980fab5..527e3c0 100644 --- a/src/irda.c +++ b/src/irda.c @@ -25,28 +25,21 @@ #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" @@ -57,88 +50,27 @@ #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 - #define ISINSTANCE(device) dc_iostream_isinstance((device), &dc_irda_vtable) #ifdef IRDA -static dc_status_t dc_irda_set_timeout (dc_iostream_t *iostream, int timeout); -static dc_status_t dc_irda_get_available (dc_iostream_t *iostream, size_t *value); -static dc_status_t dc_irda_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual); -static dc_status_t dc_irda_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual); -static dc_status_t dc_irda_close (dc_iostream_t *iostream); - -typedef struct dc_irda_t { - dc_iostream_t base; -#ifdef _WIN32 - SOCKET fd; -#else - int fd; -#endif - int timeout; -} dc_irda_t; - static const dc_iostream_vtable_t dc_irda_vtable = { - sizeof(dc_irda_t), - dc_irda_set_timeout, /* set_timeout */ + sizeof(dc_socket_t), + dc_socket_set_timeout, /* set_timeout */ NULL, /* set_latency */ NULL, /* set_halfduplex */ NULL, /* set_break */ NULL, /* set_dtr */ NULL, /* set_rts */ NULL, /* get_lines */ - dc_irda_get_available, /* get_received */ + dc_socket_get_available, /* get_received */ NULL, /* configure */ - dc_irda_read, /* read */ - dc_irda_write, /* write */ + dc_socket_read, /* read */ + dc_socket_write, /* write */ NULL, /* flush */ NULL, /* purge */ NULL, /* sleep */ - dc_irda_close, /* close */ + dc_socket_close, /* close */ }; - -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 dc_status_t @@ -146,61 +78,29 @@ 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 *) dc_iostream_allocate (context, &dc_irda_vtable); + device = (dc_socket_t *) dc_iostream_allocate (context, &dc_irda_vtable); if (device == NULL) { SYSERROR (context, S_ENOMEM); return DC_STATUS_NOMEMORY; } - // 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; - 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; + status = dc_socket_open (&device->base, AF_IRDA, SOCK_STREAM, 0); + if (status != DC_STATUS_SUCCESS) { + goto error_free; } *out = (dc_iostream_t *) device; return DC_STATUS_SUCCESS; -error_wsacleanup: -#ifdef _WIN32 - WSACleanup (); error_free: -#endif dc_iostream_deallocate ((dc_iostream_t *) device); return status; #else @@ -208,46 +108,6 @@ error_free: #endif } -#ifdef IRDA -static dc_status_t -dc_irda_close (dc_iostream_t *abstract) -{ - dc_status_t status = DC_STATUS_SUCCESS; - dc_irda_t *device = (dc_irda_t *) abstract; - - // 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 (abstract->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 (abstract->context, errcode); - dc_status_set_error(&status, syserror(errcode)); - } -#endif - - return status; -} - -static dc_status_t -dc_irda_set_timeout (dc_iostream_t *abstract, int timeout) -{ - dc_irda_t *device = (dc_irda_t *) abstract; - - device->timeout = timeout; - - return DC_STATUS_SUCCESS; -} -#endif - #define DISCOVER_MAX_DEVICES 16 // Maximum number of devices. #define DISCOVER_MAX_RETRIES 4 // Maximum number of retries. @@ -263,7 +123,7 @@ dc_status_t dc_irda_discover (dc_iostream_t *abstract, dc_irda_callback_t callback, void *userdata) { #ifdef IRDA - dc_irda_t *device = (dc_irda_t *) abstract; + dc_socket_t *device = (dc_socket_t *) abstract; if (!ISINSTANCE (abstract)) return DC_STATUS_INVALIDARGS; @@ -294,7 +154,7 @@ dc_irda_discover (dc_iostream_t *abstract, dc_irda_callback_t callback, void *us s_errcode_t errcode = S_ERRNO; if (errcode != S_EAGAIN) { SYSERROR (abstract->context, errcode); - return syserror(errcode); + return dc_socket_syserror(errcode); } } @@ -347,7 +207,7 @@ dc_status_t dc_irda_connect_name (dc_iostream_t *abstract, unsigned int address, const char *name) { #ifdef IRDA - dc_irda_t *device = (dc_irda_t *) abstract; + dc_socket_t *device = (dc_socket_t *) abstract; if (!ISINSTANCE (abstract)) return DC_STATUS_INVALIDARGS; @@ -375,13 +235,7 @@ dc_irda_connect_name (dc_iostream_t *abstract, unsigned int address, const char memset (peer.sir_name, 0x00, 25); #endif - if (connect (device->fd, (struct sockaddr *) &peer, sizeof (peer)) != 0) { - s_errcode_t errcode = S_ERRNO; - SYSERROR (abstract->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 @@ -391,7 +245,7 @@ dc_status_t dc_irda_connect_lsap (dc_iostream_t *abstract, unsigned int address, unsigned int lsap) { #ifdef IRDA - dc_irda_t *device = (dc_irda_t *) abstract; + dc_socket_t *device = (dc_socket_t *) abstract; if (!ISINSTANCE (abstract)) return DC_STATUS_INVALIDARGS; @@ -414,147 +268,8 @@ dc_irda_connect_lsap (dc_iostream_t *abstract, unsigned int address, unsigned in memset (peer.sir_name, 0x00, 25); #endif - if (connect (device->fd, (struct sockaddr *) &peer, sizeof (peer)) != 0) { - s_errcode_t errcode = S_ERRNO; - SYSERROR (abstract->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 } - -#ifdef IRDA -static dc_status_t -dc_irda_get_available (dc_iostream_t *abstract, size_t *value) -{ - dc_irda_t *device = (dc_irda_t *) abstract; - -#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 (abstract->context, errcode); - return syserror(errcode); - } - - if (value) - *value = bytes; - - return DC_STATUS_SUCCESS; -} - -static dc_status_t -dc_irda_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual) -{ - dc_status_t status = DC_STATUS_SUCCESS; - dc_irda_t *device = (dc_irda_t *) abstract; - size_t nbytes = 0; - - 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 (abstract->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 (abstract->context, errcode); - status = 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; -} - -static dc_status_t -dc_irda_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual) -{ - dc_status_t status = DC_STATUS_SUCCESS; - dc_irda_t *device = (dc_irda_t *) abstract; - size_t nbytes = 0; - - 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 (abstract->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 (abstract->context, errcode); - status = 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; -} -#endif diff --git a/src/socket.c b/src/socket.c new file mode 100644 index 0000000..948aa46 --- /dev/null +++ b/src/socket.c @@ -0,0 +1,295 @@ +/* + * 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_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_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; +} diff --git a/src/socket.h b/src/socket.h new file mode 100644 index 0000000..1a8aa18 --- /dev/null +++ b/src/socket.h @@ -0,0 +1,119 @@ +/* + * 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_get_available (dc_iostream_t *iostream, size_t *value); + +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); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* DC_SOCKET_H */ From e22ba69819a42c596e3bcb46a533124f5e71afda Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 5 May 2017 08:48:15 +0200 Subject: [PATCH 09/13] Implement the serial communication functions as no-ops For the socket based I/O stream implementations (IrDA and bluetooth) the serial communication specific functions are meaningless. Implementing them as no-ops allows the dive computer backends the call the I/O stream functions unconditionally. This is important for the bluetooth implementation, because bluetooth enabled dive computers will be able to use both the native bluetooth communication and the legacy bluetooth serial port emulation. --- src/bluetooth.c | 20 ++++++++-------- src/irda.c | 20 ++++++++-------- src/socket.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++ src/socket.h | 33 ++++++++++++++++++++++++++ 4 files changed, 116 insertions(+), 20 deletions(-) diff --git a/src/bluetooth.c b/src/bluetooth.c index 3399cd2..b139892 100644 --- a/src/bluetooth.c +++ b/src/bluetooth.c @@ -65,19 +65,19 @@ static const dc_iostream_vtable_t dc_bluetooth_vtable = { sizeof(dc_socket_t), dc_socket_set_timeout, /* set_timeout */ - NULL, /* set_latency */ - NULL, /* set_halfduplex */ - NULL, /* set_break */ - NULL, /* set_dtr */ - NULL, /* set_rts */ - NULL, /* get_lines */ + 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 */ - NULL, /* configure */ + dc_socket_configure, /* configure */ dc_socket_read, /* read */ dc_socket_write, /* write */ - NULL, /* flush */ - NULL, /* purge */ - NULL, /* sleep */ + dc_socket_flush, /* flush */ + dc_socket_purge, /* purge */ + dc_socket_sleep, /* sleep */ dc_socket_close, /* close */ }; diff --git a/src/irda.c b/src/irda.c index 527e3c0..149808a 100644 --- a/src/irda.c +++ b/src/irda.c @@ -56,19 +56,19 @@ static const dc_iostream_vtable_t dc_irda_vtable = { sizeof(dc_socket_t), dc_socket_set_timeout, /* set_timeout */ - NULL, /* set_latency */ - NULL, /* set_halfduplex */ - NULL, /* set_break */ - NULL, /* set_dtr */ - NULL, /* set_rts */ - NULL, /* get_lines */ + 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 */ - NULL, /* configure */ + dc_socket_configure, /* configure */ dc_socket_read, /* read */ dc_socket_write, /* write */ - NULL, /* flush */ - NULL, /* purge */ - NULL, /* sleep */ + dc_socket_flush, /* flush */ + dc_socket_purge, /* purge */ + dc_socket_sleep, /* sleep */ dc_socket_close, /* close */ }; #endif diff --git a/src/socket.c b/src/socket.c index 948aa46..5ce392f 100644 --- a/src/socket.c +++ b/src/socket.c @@ -163,6 +163,45 @@ dc_socket_set_timeout (dc_iostream_t *abstract, int 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) { @@ -186,6 +225,12 @@ dc_socket_get_available (dc_iostream_t *abstract, size_t *value) 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) { @@ -293,3 +338,21 @@ out: 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 index 1a8aa18..d612603 100644 --- a/src/socket.h +++ b/src/socket.h @@ -104,15 +104,48 @@ dc_socket_connect (dc_iostream_t *iostream, const struct sockaddr *addr, s_sockl 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 */ From 76187c550a806fe422920eb8795fa687244513f1 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 23 Nov 2017 21:39:53 +0100 Subject: [PATCH 10/13] Detect dives with invalid profile data The OSTC3 stores the dive headers and profile data in two separate memory areas. There is a header area with fixed positions and a profile area which is used as a ring buffer. Each dive header stores the position of the profile data in the ring buffer. Now, once there are more dive headers then room for the profiles, the oldest profiles (but not the headers) are overwritten with new data. Because the dive headers are not updated when their profile data gets overwritten, they will now point to data that is no longer available. The internal logbook detects this situation and does not display the profile. But during the download, there is no such check, and the OSTC will send invalid profile data. This invalid profile data should be dropped on the receiver side. Unfortunately implementing the exact same check as is done by the OSTC itself isn't possible, because the OSTC doesn't send the 6 byte internal header on which the check is based. As a workaround, the two byte end-of-profile marker and the length field in the profile header is used to detect overwritten profiles. --- src/hw_ostc3.c | 25 +++++++++++++++++++++++++ src/hw_ostc_parser.c | 7 +++++++ 2 files changed, 32 insertions(+) diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index 6f0354f..e240342 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -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 a96456c..04b9d6f 100644 --- a/src/hw_ostc_parser.c +++ b/src/hw_ostc_parser.c @@ -569,6 +569,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) { From f87720dff9e04dbe03b668a85335012c4eb16f41 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 27 Nov 2017 21:58:24 +0100 Subject: [PATCH 11/13] Add support for semi-closed circuit diving Add a new type to distinguish between closed circuit (CCR) and semi-closed circuit (SCR) diving. Some dive computers from HW and DiveSystem/Ratio support this. Because the CCR/SCR abbreviations are more commonly used, let's take the opportunity to also rename the existing DC_DIVEMODE_CC. To preserve backwards compatibility, a macro is added to map the old name to the new one. Reported-by: Jan Mulder --- doc/man/dc_parser_get_field.3 | 6 ++++-- examples/output_xml.c | 2 +- include/libdivecomputer/parser.h | 6 +++++- src/atomics_cobalt_parser.c | 2 +- src/divesystem_idive_parser.c | 4 +++- src/hw_ostc_parser.c | 10 ++++++++-- src/shearwater_predator_parser.c | 2 +- src/suunto_d9_parser.c | 2 +- src/suunto_eonsteel_parser.c | 2 +- 9 files changed, 25 insertions(+), 11 deletions(-) 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 bb88b2c..b66fc27 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/parser.h b/include/libdivecomputer/parser.h index 133b252..1b53fd3 100644 --- a/include/libdivecomputer/parser.h +++ b/include/libdivecomputer/parser.h @@ -121,9 +121,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/src/atomics_cobalt_parser.c b/src/atomics_cobalt_parser.c index e16077b..438eb39 100644 --- a/src/atomics_cobalt_parser.c +++ b/src/atomics_cobalt_parser.c @@ -202,7 +202,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/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_ostc_parser.c b/src/hw_ostc_parser.c index 04b9d6f..acf1592 100644 --- a/src/hw_ostc_parser.c +++ b/src/hw_ostc_parser.c @@ -59,6 +59,7 @@ #define OSTC3_CC 1 #define OSTC3_GAUGE 2 #define OSTC3_APNEA 3 +#define OSTC3_PSCR 4 #define OSTC4 0x3B @@ -505,8 +506,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; @@ -529,7 +532,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; @@ -537,6 +540,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; } diff --git a/src/shearwater_predator_parser.c b/src/shearwater_predator_parser.c index 8100a9f..8abd0f9 100644 --- a/src/shearwater_predator_parser.c +++ b/src/shearwater_predator_parser.c @@ -265,7 +265,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/suunto_d9_parser.c b/src/suunto_d9_parser.c index 1f89fe4..09304d3 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -382,7 +382,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_eonsteel_parser.c b/src/suunto_eonsteel_parser.c index a7f817d..8a06f9d 100644 --- a/src/suunto_eonsteel_parser.c +++ b/src/suunto_eonsteel_parser.c @@ -1328,7 +1328,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 0; From 42f8e012b74007c3c889e1bbfcc2c4d1e4be3ebc Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 30 Nov 2017 22:47:12 +0100 Subject: [PATCH 12/13] Don't accept a NULL pointer as parameter Immediately return an error instead of trying to pass the NULL pointer to the underlying open system call. --- src/serial_posix.c | 4 ++-- src/serial_win32.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/serial_posix.c b/src/serial_posix.c index 7b79ecc..fecc018 100644 --- a/src/serial_posix.c +++ b/src/serial_posix.c @@ -181,10 +181,10 @@ 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 : ""); + INFO (context, "Open: name=%s", name); // Allocate memory. device = (dc_serial_t *) dc_iostream_allocate (context, &dc_serial_vtable); diff --git a/src/serial_win32.c b/src/serial_win32.c index fb9940b..4454a74 100644 --- a/src/serial_win32.c +++ b/src/serial_win32.c @@ -161,15 +161,15 @@ 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 : ""); + 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; From ca1efdcecdac3348b1125fcd0266ab12cfc20154 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Wed, 6 Dec 2017 21:23:19 -0600 Subject: [PATCH 13/13] Correctly determine git SHA if libdivecomputer is a git submodule In the case of a submodule, the .git file is a text file pointing to the correct module in the parent's .git folder. The git rev-parse works correctly in both cases. Signed-off-by: Dirk Hohndel --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 586b89b..3b1357b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -100,7 +100,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 $@; \