Hi there,

I attached some patches which can be used to make the *libdivecomputer *
project to accept callbacks to custom functions used for serial
communication.

As I mentioned in my weekly report, I am not sure if I made the best
decisions
on the implementation.

I tested the HW OSTC 3 family with my OSTCs device and the native serial
communication works. I also implemented a custom implementation using
the QtBluetooth API and  I managed to transfer the dive logs without any
problems.

Best wishes,
Claudiu
From bf1b6d33f27aca31012acbf8ab2fd6f907ce92db Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <[email protected]>
Date: Fri, 26 Jun 2015 00:57:21 +0300
Subject: [PATCH 01/13] Extend the transport enum descriptor for serial
 communication

Add a new transport type which can be used to identify
Bluetooth serial communication.

Signed-off-by: Claudiu Olteanu <[email protected]>
---
 include/libdivecomputer/descriptor.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/libdivecomputer/descriptor.h b/include/libdivecomputer/descriptor.h
index 6f9735d..f1c815d 100644
--- a/include/libdivecomputer/descriptor.h
+++ b/include/libdivecomputer/descriptor.h
@@ -33,7 +33,8 @@ typedef enum dc_transport_t {
 	DC_TRANSPORT_NONE,
 	DC_TRANSPORT_SERIAL,
 	DC_TRANSPORT_USB,
-	DC_TRANSPORT_IRDA
+	DC_TRANSPORT_IRDA,
+	DC_TRANSPORT_BLUETOOTH
 } dc_transport_t;
 
 typedef struct dc_descriptor_t dc_descriptor_t;
-- 
2.1.4

From 6b317131f96276f494e049d5597ff86d9f830383 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <[email protected]>
Date: Fri, 26 Jun 2015 01:00:59 +0300
Subject: [PATCH 02/13] Create a generic structure to represent any type of
 serial communication

Add a structure which holds references to basic operations
on a serial communication. This can be used to pass a set
of function pointer callbacks in order to create a custom
implementation for serial communication.

Add a generic structure to represent the needed information
for a serial communication.

Signed-off-by: Claudiu Olteanu <[email protected]>
---
 include/libdivecomputer/custom_serial.h | 58 +++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)
 create mode 100644 include/libdivecomputer/custom_serial.h

diff --git a/include/libdivecomputer/custom_serial.h b/include/libdivecomputer/custom_serial.h
new file mode 100644
index 0000000..788a062
--- /dev/null
+++ b/include/libdivecomputer/custom_serial.h
@@ -0,0 +1,58 @@
+/*
+ * libdivecomputer
+ *
+ * Copyright (C) 2008 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 CUSTOM_SERIAL_H
+#define CUSTOM_SERIAL_H
+
+#include <string.h>
+
+#include "context.h"
+#include "descriptor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct serial_t serial_t;
+
+typedef struct dc_serial_operations_t
+{
+	//TODO in the end serial_t should be replaced with  dc_serial_t
+	int (*open) (serial_t **device, dc_context_t *context);
+	int (*close) (serial_t *device);
+	int (*read) (serial_t *device, void* data, unsigned int size);
+	int (*write) (serial_t *device, const void* data, unsigned int size);
+	int (*flush) (serial_t *device, int queue);
+} dc_serial_operations_t;
+
+typedef struct dc_serial_t {
+	dc_context_t *context;			//context
+	int fd;					//file descriptor
+	long timeout;				//timeout
+	dc_transport_t type;			//the type of the transport (USB, SERIAL, IRDA, BLUETOOTH)
+	void *data;				//specific data for serial device
+	const dc_serial_operations_t *ops;	//reference to a custom set of operations
+} dc_serial_t;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* CUSTOM_SERIAL_H */
-- 
2.1.4

From a5b9b005b3017f06e9093cf4852a778a5fbf2782 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <[email protected]>
Date: Fri, 26 Jun 2015 01:06:04 +0300
Subject: [PATCH 03/13] Implement initialization method for serial device

The method can be used to set some specific data for a
device and to pass a set of function pointer callbacks for
operations needed in the serial communication.

Signed-off-by: Claudiu Olteanu <[email protected]>
---
 include/libdivecomputer/custom_serial.h |  2 ++
 src/custom_serial.c                     | 30 ++++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+)
 create mode 100644 src/custom_serial.c

diff --git a/include/libdivecomputer/custom_serial.h b/include/libdivecomputer/custom_serial.h
index 788a062..ae0143d 100644
--- a/include/libdivecomputer/custom_serial.h
+++ b/include/libdivecomputer/custom_serial.h
@@ -52,6 +52,8 @@ typedef struct dc_serial_t {
 	const dc_serial_operations_t *ops;	//reference to a custom set of operations
 } dc_serial_t;
 
+void serial_init(dc_serial_t *device, void *data, const dc_serial_operations_t *ops);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/src/custom_serial.c b/src/custom_serial.c
new file mode 100644
index 0000000..aa50b59
--- /dev/null
+++ b/src/custom_serial.c
@@ -0,0 +1,30 @@
+/*
+ * libdivecomputer
+ *
+ * Copyright (C) 2008 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 <libdivecomputer/custom_serial.h>
+
+void
+serial_init(dc_serial_t *device, void *data, const dc_serial_operations_t *ops)
+{
+	memset(device, 0, sizeof (*device));
+	device->data = data;
+	device->ops = ops;
+}
-- 
2.1.4

From df5296b9e8f76fcadf4c6590d903c54b991e6619 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <[email protected]>
Date: Fri, 26 Jun 2015 01:11:08 +0300
Subject: [PATCH 04/13] Add targets for custom serial source to Makefile

Signed-off-by: Claudiu Olteanu <[email protected]>
---
 src/Makefile.am | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index abbaa48..0c60d02 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -59,7 +59,8 @@ libdivecomputer_la_SOURCES = \
 	ringbuffer.h ringbuffer.c \
 	checksum.h checksum.c \
 	array.h array.c \
-	buffer.c
+	buffer.c \
+	custom_serial.c
 
 if OS_WIN32
 libdivecomputer_la_SOURCES += serial.h serial_win32.c
-- 
2.1.4

From bf9602462ac62a63fbe84fe4c9c5e1979eec7a08 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <[email protected]>
Date: Fri, 26 Jun 2015 01:13:09 +0300
Subject: [PATCH 05/13] Add a new parameter for serial open method

This parameter is temporary. We use it to respect the signature
of the native serial open method. In this way we don't need to
modify the old implementation of native serial communication.

Signed-off-by: Claudiu Olteanu <[email protected]>
---
 include/libdivecomputer/custom_serial.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/libdivecomputer/custom_serial.h b/include/libdivecomputer/custom_serial.h
index ae0143d..cf005f4 100644
--- a/include/libdivecomputer/custom_serial.h
+++ b/include/libdivecomputer/custom_serial.h
@@ -36,7 +36,7 @@ typedef struct serial_t serial_t;
 typedef struct dc_serial_operations_t
 {
 	//TODO in the end serial_t should be replaced with  dc_serial_t
-	int (*open) (serial_t **device, dc_context_t *context);
+	int (*open) (serial_t **device, dc_context_t *context, const char *name);
 	int (*close) (serial_t *device);
 	int (*read) (serial_t *device, void* data, unsigned int size);
 	int (*write) (serial_t *device, const void* data, unsigned int size);
-- 
2.1.4

From 352c073052b4ed36205bfff6691da7db8dcb6c9a Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <[email protected]>
Date: Fri, 26 Jun 2015 01:23:40 +0300
Subject: [PATCH 06/13] Implement open method for native serial communication

Create a method which can be used to initialize
libdc's implementation for native serial communication.

Signed-off-by: Claudiu Olteanu <[email protected]>
---
 include/libdivecomputer/custom_serial.h |  3 +++
 src/custom_serial.c                     | 48 +++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+)

diff --git a/include/libdivecomputer/custom_serial.h b/include/libdivecomputer/custom_serial.h
index cf005f4..856facd 100644
--- a/include/libdivecomputer/custom_serial.h
+++ b/include/libdivecomputer/custom_serial.h
@@ -23,6 +23,7 @@
 #define CUSTOM_SERIAL_H
 
 #include <string.h>
+#include <stdlib.h>
 
 #include "context.h"
 #include "descriptor.h"
@@ -54,6 +55,8 @@ typedef struct dc_serial_t {
 
 void serial_init(dc_serial_t *device, void *data, const dc_serial_operations_t *ops);
 
+dc_status_t dc_serial_native_open(dc_serial_t **serial, dc_context_t *context, const char *devname);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/src/custom_serial.c b/src/custom_serial.c
index aa50b59..56ac619 100644
--- a/src/custom_serial.c
+++ b/src/custom_serial.c
@@ -20,6 +20,18 @@
  */
 
 #include <libdivecomputer/custom_serial.h>
+#include <serial.h>
+
+#include "context-private.h"
+
+const dc_serial_operations_t native_serial_ops = {
+	.open = serial_open,
+	.close = serial_close,
+	.read = serial_read,
+	.write = serial_write,
+	.flush = serial_flush
+};
+
 
 void
 serial_init(dc_serial_t *device, void *data, const dc_serial_operations_t *ops)
@@ -28,3 +40,39 @@ serial_init(dc_serial_t *device, void *data, const dc_serial_operations_t *ops)
 	device->data = data;
 	device->ops = ops;
 }
+
+
+dc_status_t
+dc_serial_native_open(dc_serial_t **out, dc_context_t *context, const char *devname)
+{
+	if (out == NULL)
+		return DC_STATUS_INVALIDARGS;
+
+	// Allocate memory.
+	dc_serial_t *serial_device = (dc_serial_t *) malloc (sizeof (dc_serial_t));
+
+	if (serial_device == NULL) {
+		ERROR (context, "Failed to allocate memory.");
+		return DC_STATUS_NOMEMORY;
+	}
+
+	serial_t *port;
+
+	// Open the serial device.
+	int rc = serial_open (&port, context, devname);
+	if (rc == -1) {
+		ERROR (context, "Failed to open the serial port.");
+		free (serial_device);
+		return DC_STATUS_IO;
+	}
+
+	// Initialize data and function pointers
+	serial_init(serial_device, port, &native_serial_ops);
+
+	// Set the type of the device
+	serial_device->type = DC_TRANSPORT_SERIAL;
+
+	*out = serial_device;
+
+	return DC_STATUS_SUCCESS;
+}
-- 
2.1.4

From 76826e44547fbc4fbf757297ac032a5dfb8eccfc Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <[email protected]>
Date: Fri, 26 Jun 2015 01:26:18 +0300
Subject: [PATCH 07/13] Add dc_ prefix to custom serial open method

Signed-off-by: Claudiu Olteanu <[email protected]>
---
 include/libdivecomputer/custom_serial.h | 2 +-
 src/custom_serial.c                     | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/libdivecomputer/custom_serial.h b/include/libdivecomputer/custom_serial.h
index 856facd..f1c8c3f 100644
--- a/include/libdivecomputer/custom_serial.h
+++ b/include/libdivecomputer/custom_serial.h
@@ -53,7 +53,7 @@ typedef struct dc_serial_t {
 	const dc_serial_operations_t *ops;	//reference to a custom set of operations
 } dc_serial_t;
 
-void serial_init(dc_serial_t *device, void *data, const dc_serial_operations_t *ops);
+void dc_serial_init(dc_serial_t *device, void *data, const dc_serial_operations_t *ops);
 
 dc_status_t dc_serial_native_open(dc_serial_t **serial, dc_context_t *context, const char *devname);
 
diff --git a/src/custom_serial.c b/src/custom_serial.c
index 56ac619..34f0936 100644
--- a/src/custom_serial.c
+++ b/src/custom_serial.c
@@ -34,7 +34,7 @@ const dc_serial_operations_t native_serial_ops = {
 
 
 void
-serial_init(dc_serial_t *device, void *data, const dc_serial_operations_t *ops)
+dc_serial_init(dc_serial_t *device, void *data, const dc_serial_operations_t *ops)
 {
 	memset(device, 0, sizeof (*device));
 	device->data = data;
@@ -67,7 +67,7 @@ dc_serial_native_open(dc_serial_t **out, dc_context_t *context, const char *devn
 	}
 
 	// Initialize data and function pointers
-	serial_init(serial_device, port, &native_serial_ops);
+	dc_serial_init(serial_device, port, &native_serial_ops);
 
 	// Set the type of the device
 	serial_device->type = DC_TRANSPORT_SERIAL;
-- 
2.1.4

From fbbc7bea43b564831f673df8c91425270645f00a Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <[email protected]>
Date: Fri, 26 Jun 2015 01:29:07 +0300
Subject: [PATCH 08/13] Add get_received and get_transmitted functions pointers

Extend the native serial operations structure with new
methods used to get the transmitted number of bytes and
the received one.

Signed-off-by: Claudiu Olteanu <[email protected]>
---
 include/libdivecomputer/custom_serial.h | 2 ++
 src/custom_serial.c                     | 4 +++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/libdivecomputer/custom_serial.h b/include/libdivecomputer/custom_serial.h
index f1c8c3f..b3600b6 100644
--- a/include/libdivecomputer/custom_serial.h
+++ b/include/libdivecomputer/custom_serial.h
@@ -42,6 +42,8 @@ typedef struct dc_serial_operations_t
 	int (*read) (serial_t *device, void* data, unsigned int size);
 	int (*write) (serial_t *device, const void* data, unsigned int size);
 	int (*flush) (serial_t *device, int queue);
+	int (*get_received) (serial_t *device);
+	int (*get_transmitted) (serial_t *device);
 } dc_serial_operations_t;
 
 typedef struct dc_serial_t {
diff --git a/src/custom_serial.c b/src/custom_serial.c
index 34f0936..06f7724 100644
--- a/src/custom_serial.c
+++ b/src/custom_serial.c
@@ -29,7 +29,9 @@ const dc_serial_operations_t native_serial_ops = {
 	.close = serial_close,
 	.read = serial_read,
 	.write = serial_write,
-	.flush = serial_flush
+	.flush = serial_flush,
+	.get_received = serial_get_received,
+	.get_transmitted = serial_get_transmitted
 };
 
 
-- 
2.1.4

From c4735d56e25c2366309739572af304d125ab8018 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <[email protected]>
Date: Fri, 26 Jun 2015 01:44:39 +0300
Subject: [PATCH 09/13] Use the dc_serial_t structure in HW OSTC family

Open a native serial device and use it in the HW OSTC
implementation.

This patch replaces the old serial structure with the
new one, used for custom implementations.

Signed-off-by: Claudiu Olteanu <[email protected]>
---
 include/libdivecomputer/hw_ostc.h |  1 +
 src/hw_ostc.c                     | 66 ++++++++++++++++++++-------------------
 2 files changed, 35 insertions(+), 32 deletions(-)

diff --git a/include/libdivecomputer/hw_ostc.h b/include/libdivecomputer/hw_ostc.h
index 91fe714..52ef81b 100644
--- a/include/libdivecomputer/hw_ostc.h
+++ b/include/libdivecomputer/hw_ostc.h
@@ -26,6 +26,7 @@
 #include "device.h"
 #include "parser.h"
 #include "buffer.h"
+#include "custom_serial.h"
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/src/hw_ostc.c b/src/hw_ostc.c
index d994d38..ee7e17e 100644
--- a/src/hw_ostc.c
+++ b/src/hw_ostc.c
@@ -64,7 +64,7 @@
 
 typedef struct hw_ostc_device_t {
 	dc_device_t base;
-	serial_t *port;
+	dc_serial_t *serial;
 	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};
-	int n = serial_write (device->port, command, sizeof (command));
+	int n = serial_write (device->serial->data, command, sizeof (command));
 	if (n != sizeof (command)) {
 		ERROR (abstract->context, "Failed to send the command.");
 		return EXITCODE (n);
@@ -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};
-		n = serial_read (device->port, answer, sizeof (answer));
+		n = serial_read (device->serial->data, answer, sizeof (answer));
 		if (n != sizeof (answer)) {
 			ERROR (abstract->context, "Failed to receive the echo.");
 			return EXITCODE (n);
@@ -139,11 +139,11 @@ hw_ostc_device_open (dc_device_t **out, dc_context_t *context, const char *name)
 	device_init (&device->base, context, &hw_ostc_device_vtable);
 
 	// Set the default values.
-	device->port = NULL;
+	device->serial = NULL;
 	memset (device->fingerprint, 0, sizeof (device->fingerprint));
 
 	// Open the device.
-	int rc = serial_open (&device->port, context, name);
+	int rc = dc_serial_native_open (&device->serial, context, name);
 	if (rc == -1) {
 		ERROR (context, "Failed to open the serial port.");
 		free (device);
@@ -151,25 +151,25 @@ hw_ostc_device_open (dc_device_t **out, dc_context_t *context, const char *name)
 	}
 
 	// Set the serial communication protocol (115200 8N1).
-	rc = serial_configure (device->port, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
+	rc = serial_configure (device->serial->data, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
 	if (rc == -1) {
 		ERROR (context, "Failed to set the terminal attributes.");
-		serial_close (device->port);
+		device->serial->ops->close (device->serial->data);
 		free (device);
 		return DC_STATUS_IO;
 	}
 
 	// Set the timeout for receiving data.
-	if (serial_set_timeout (device->port, 4000) == -1) {
+	if (serial_set_timeout (device->serial->data, 4000) == -1) {
 		ERROR (context, "Failed to set the timeout.");
-		serial_close (device->port);
+		device->serial->ops->close (device->serial->data);
 		free (device);
 		return DC_STATUS_IO;
 	}
 
 	// Make sure everything is in a sane state.
-	serial_sleep (device->port, 100);
-	serial_flush (device->port, SERIAL_QUEUE_BOTH);
+	serial_sleep (device->serial->data, 100);
+	device->serial->ops->flush (device->serial->data, SERIAL_QUEUE_BOTH);
 
 	*out = (dc_device_t*) device;
 
@@ -183,7 +183,7 @@ hw_ostc_device_close (dc_device_t *abstract)
 	hw_ostc_device_t *device = (hw_ostc_device_t*) abstract;
 
 	// Close the device.
-	if (serial_close (device->port) == -1) {
+	if (device->serial->ops->close (device->serial->data) == -1) {
 		free (device);
 		return DC_STATUS_IO;
 	}
@@ -230,7 +230,7 @@ hw_ostc_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
 
 	// Send the command.
 	unsigned char command[1] = {'a'};
-	int rc = serial_write (device->port, command, sizeof (command));
+	int rc = device->serial->ops->write (device->serial->data, command, sizeof (command));
 	if (rc != sizeof (command)) {
 		ERROR (abstract->context, "Failed to send the command.");
 		return EXITCODE (rc);
@@ -238,7 +238,7 @@ hw_ostc_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
 
 	// Read the header.
 	unsigned char header[SZ_HEADER] = {0};
-	int n = serial_read (device->port, header, sizeof (header));
+	int n = device->serial->ops->read (device->serial->data, header, sizeof (header));
 	if (n != sizeof (header)) {
 		ERROR (abstract->context, "Failed to receive the header.");
 		return EXITCODE (n);
@@ -283,7 +283,7 @@ hw_ostc_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
 		unsigned int len = 1024;
 
 		// Increase the packet size if more data is immediately available.
-		int available = serial_get_received (device->port);
+		int available = device->serial->ops->get_received (device->serial->data);
 		if (available > len)
 			len = available;
 
@@ -292,7 +292,7 @@ hw_ostc_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
 			len = size - nbytes;
 
 		// Read the packet.
-		int n = serial_read (device->port, data + nbytes, len);
+		int n = device->serial->ops->read (device->serial->data, data + nbytes, len);
 		if (n != len) {
 			ERROR (abstract->context, "Failed to receive the answer.");
 			return EXITCODE (n);
@@ -365,7 +365,7 @@ hw_ostc_device_md2hash (dc_device_t *abstract, unsigned char data[], unsigned in
 		return rc;
 
 	// Read the answer.
-	int n = serial_read (device->port, data, SZ_MD2HASH);
+	int n = device->serial->ops->read (device->serial->data, data, SZ_MD2HASH);
 	if (n != SZ_MD2HASH) {
 		ERROR (abstract->context, "Failed to receive the answer.");
 		return EXITCODE (n);
@@ -397,7 +397,7 @@ hw_ostc_device_clock (dc_device_t *abstract, const dc_datetime_t *datetime)
 	unsigned char packet[6] = {
 		datetime->hour, datetime->minute, datetime->second,
 		datetime->month, datetime->day, datetime->year - 2000};
-	int n = serial_write (device->port, packet, sizeof (packet));
+	int n = device->serial->ops->write (device->serial->data, packet, sizeof (packet));
 	if (n != sizeof (packet)) {
 		ERROR (abstract->context, "Failed to send the data packet.");
 		return EXITCODE (n);
@@ -432,7 +432,7 @@ hw_ostc_device_eeprom_read (dc_device_t *abstract, unsigned int bank, unsigned c
 		return rc;
 
 	// Read the answer.
-	int n = serial_read (device->port, data, SZ_EEPROM);
+	int n = device->serial->ops->read (device->serial->data, data, SZ_EEPROM);
 	if (n != SZ_EEPROM) {
 		ERROR (abstract->context, "Failed to receive the answer.");
 		return EXITCODE (n);
@@ -552,7 +552,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};
-		int n = serial_read (device->port, raw, 1);
+		int n = device->serial->ops->read (device->serial->data, raw, 1);
 		if (n != 1) {
 			ERROR (abstract->context, "Failed to receive the packet.");
 			return EXITCODE (n);
@@ -570,7 +570,7 @@ hw_ostc_device_screenshot (dc_device_t *abstract, dc_buffer_t *buffer, hw_ostc_f
 			count &= 0x3F;
 		} else {
 			// Color pixel.
-			n = serial_read (device->port, raw + 1, 2);
+			n = device->serial->ops->read (device->serial->data, raw + 1, 2);
 			if (n != 2) {
 				ERROR (abstract->context, "Failed to receive the packet.");
 				return EXITCODE (n);
@@ -769,7 +769,7 @@ hw_ostc_firmware_setup_internal (hw_ostc_device_t *device)
 
 	// Send the command.
 	unsigned char command[1] = {0xC1};
-	int n = serial_write (device->port, command, sizeof (command));
+	int n = device->serial->ops->write (device->serial->data, command, sizeof (command));
 	if (n != sizeof (command)) {
 		ERROR (abstract->context, "Failed to send the command.");
 		return EXITCODE (n);
@@ -777,7 +777,7 @@ hw_ostc_firmware_setup_internal (hw_ostc_device_t *device)
 
 	// Read the response.
 	unsigned char answer[2] = {0};
-	n = serial_read (device->port, answer, sizeof (answer));
+	n = device->serial->ops->read (device->serial->data, answer, sizeof (answer));
 	if (n != sizeof (answer)) {
 		ERROR (abstract->context, "Failed to receive the response.");
 		return EXITCODE (n);
@@ -819,7 +819,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.
-	int n = serial_write (device->port, data, size);
+	int n = device->serial->ops->write (device->serial->data, data, size);
 	if (n != size) {
 		ERROR (abstract->context, "Failed to send the packet.");
 		return EXITCODE (n);
@@ -827,7 +827,7 @@ hw_ostc_firmware_write_internal (hw_ostc_device_t *device, unsigned char *data,
 
 	// Read the response.
 	unsigned char answer[1] = {0};
-	n = serial_read (device->port, answer, sizeof (answer));
+	n = device->serial->ops->read (device->serial->data, answer, sizeof (answer));
 	if (n != sizeof (answer)) {
 		ERROR (abstract->context, "Failed to receive the response.");
 		return EXITCODE (n);
@@ -899,16 +899,18 @@ hw_ostc_device_fwupdate (dc_device_t *abstract, const char *filename)
 	// bootloader needs to be send repeatedly, until the response packet is
 	// received. Thus the time between each two attempts is directly controlled
 	// by the timeout value.
-	serial_set_timeout (device->port, 300);
+	serial_set_timeout (device->serial->data, 300);
 
 	// Setup the bootloader.
 	const unsigned int baudrates[] = {19200, 115200};
 	for (unsigned int i = 0; i < C_ARRAY_SIZE(baudrates); ++i) {
-		// Adjust the baudrate.
-		if (serial_configure (device->port, baudrates[i], 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE) == -1) {
-			ERROR (abstract->context, "Failed to set the terminal attributes.");
-			free (firmware);
-			return DC_STATUS_IO;
+		if (device->serial->type == DC_TRANSPORT_SERIAL) {
+			// Adjust the baudrate.
+			if (serial_configure (device->serial->data, baudrates[i], 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE) == -1) {
+				ERROR (abstract->context, "Failed to set the terminal attributes.");
+				free (firmware);
+				return DC_STATUS_IO;
+			}
 		}
 
 		// Try to setup the bootloader.
@@ -924,7 +926,7 @@ hw_ostc_device_fwupdate (dc_device_t *abstract, const char *filename)
 	}
 
 	// Increase the timeout again.
-	serial_set_timeout (device->port, 1000);
+	serial_set_timeout (device->serial->data, 1000);
 
 	// Enable progress notifications.
 	dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
-- 
2.1.4

From 5930839024281a2faec793c3a28c26b59e29b525 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <[email protected]>
Date: Fri, 26 Jun 2015 01:51:59 +0300
Subject: [PATCH 10/13] Use the dc_serial_t structure in HW OSTC family 3

Open a native serial device and use it in the HW OSTC3
implementation.

This patch replaces the old serial structure with the
new one, used for custom implementations.

Signed-off-by: Claudiu Olteanu <[email protected]>
---
 include/libdivecomputer/hw_ostc3.h |  1 +
 src/hw_ostc3.c                     | 40 +++++++++++++++++++-------------------
 2 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/include/libdivecomputer/hw_ostc3.h b/include/libdivecomputer/hw_ostc3.h
index c60dc63..047401b 100644
--- a/include/libdivecomputer/hw_ostc3.h
+++ b/include/libdivecomputer/hw_ostc3.h
@@ -26,6 +26,7 @@
 #include "device.h"
 #include "parser.h"
 #include "buffer.h"
+#include "custom_serial.h"
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c
index a221fb2..305bb80 100644
--- a/src/hw_ostc3.c
+++ b/src/hw_ostc3.c
@@ -88,7 +88,7 @@ typedef enum hw_ostc3_state_t {
 
 typedef struct hw_ostc3_device_t {
 	dc_device_t base;
-	serial_t *port;
+	dc_serial_t *serial;
 	unsigned char fingerprint[5];
 	hw_ostc3_state_t state;
 } hw_ostc3_device_t;
@@ -163,7 +163,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
 
 	// Send the command.
 	unsigned char command[1] = {cmd};
-	int n = serial_write (device->port, command, sizeof (command));
+	int n = device->serial->ops->write (device->serial->data, command, sizeof (command));
 	if (n != sizeof (command)) {
 		ERROR (abstract->context, "Failed to send the command.");
 		return EXITCODE (n);
@@ -171,7 +171,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
 
 	// Read the echo.
 	unsigned char echo[1] = {0};
-	n = serial_read (device->port, echo, sizeof (echo));
+	n = device->serial->ops->read (device->serial->data, echo, sizeof (echo));
 	if (n != sizeof (echo)) {
 		ERROR (abstract->context, "Failed to receive the echo.");
 		return EXITCODE (n);
@@ -190,7 +190,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
 
 	if (input) {
 		// Send the input data packet.
-		n = serial_write (device->port, input, isize);
+		n = device->serial->ops->write (device->serial->data, input, isize);
 		if (n != isize) {
 			ERROR (abstract->context, "Failed to send the data packet.");
 			return EXITCODE (n);
@@ -204,7 +204,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
 			unsigned int len = 1024;
 
 			// Increase the packet size if more data is immediately available.
-			int available = serial_get_received (device->port);
+			int available = device->serial->ops->get_received (device->serial->data);
 			if (available > len)
 				len = available;
 
@@ -213,7 +213,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
 				len = osize - nbytes;
 
 			// Read the packet.
-			n = serial_read (device->port, output + nbytes, len);
+			n = device->serial->ops->read (device->serial->data, output + nbytes, len);
 			if (n != len) {
 				ERROR (abstract->context, "Failed to receive the answer.");
 				return EXITCODE (n);
@@ -232,7 +232,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
 	if (cmd != EXIT) {
 		// Read the ready byte.
 		unsigned char answer[1] = {0};
-		n = serial_read (device->port, answer, sizeof (answer));
+		n = device->serial->ops->read (device->serial->data, answer, sizeof (answer));
 		if (n != sizeof (answer)) {
 			ERROR (abstract->context, "Failed to receive the ready byte.");
 			return EXITCODE (n);
@@ -266,11 +266,11 @@ hw_ostc3_device_open (dc_device_t **out, dc_context_t *context, const char *name
 	device_init (&device->base, context, &hw_ostc3_device_vtable);
 
 	// Set the default values.
-	device->port = NULL;
+	device->serial = NULL;
 	memset (device->fingerprint, 0, sizeof (device->fingerprint));
 
 	// Open the device.
-	int rc = serial_open (&device->port, context, name);
+	int rc = dc_serial_native_open (&device->serial, context, name);
 	if (rc == -1) {
 		ERROR (context, "Failed to open the serial port.");
 		free (device);
@@ -278,25 +278,25 @@ hw_ostc3_device_open (dc_device_t **out, dc_context_t *context, const char *name
 	}
 
 	// Set the serial communication protocol (115200 8N1).
-	rc = serial_configure (device->port, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
+	rc = serial_configure (device->serial->data, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
 	if (rc == -1) {
 		ERROR (context, "Failed to set the terminal attributes.");
-		serial_close (device->port);
+		device->serial->ops->close (device->serial->data);
 		free (device);
 		return DC_STATUS_IO;
 	}
 
 	// Set the timeout for receiving data (3000ms).
-	if (serial_set_timeout (device->port, 3000) == -1) {
+	if (serial_set_timeout (device->serial->data, 3000) == -1) {
 		ERROR (context, "Failed to set the timeout.");
-		serial_close (device->port);
+		device->serial->ops->close (device->serial->data);
 		free (device);
 		return DC_STATUS_IO;
 	}
 
 	// Make sure everything is in a sane state.
-	serial_sleep (device->port, 300);
-	serial_flush (device->port, SERIAL_QUEUE_BOTH);
+	serial_sleep (device->serial->data, 300);
+	device->serial->ops->flush (device->serial->data, SERIAL_QUEUE_BOTH);
 
 	device->state = OPEN;
 
@@ -336,17 +336,17 @@ hw_ostc3_device_init_service (hw_ostc3_device_t *device)
 	int n = 0;
 
 	// We cant use hw_ostc3_transfer here, due to the different echos
-	n = serial_write (device->port, command, sizeof (command));
+	n = device->serial->ops->write (device->serial->data, command, sizeof (command));
 	if (n != sizeof (command)) {
 		ERROR (context, "Failed to send the command.");
 		return EXITCODE (n);
 	}
 
 	// Give the device some time to enter service mode
-	serial_sleep (device->port, 100);
+	serial_sleep (device->serial->data, 100);
 
 	// Read the response
-	n = serial_read (device->port, output, sizeof (output));
+	n = device->serial->ops->read (device->serial->data, output, sizeof (output));
 	if (n != sizeof (output)) {
 		ERROR (context, "Failed to receive the echo.");
 		return EXITCODE (n);
@@ -408,14 +408,14 @@ hw_ostc3_device_close (dc_device_t *abstract)
 		rc = hw_ostc3_transfer (device, NULL, EXIT, NULL, 0, NULL, 0);
 		if (rc != DC_STATUS_SUCCESS) {
 			ERROR (abstract->context, "Failed to send the command.");
-			serial_close (device->port);
+			device->serial->ops->close (device->serial->data);
 			free (device);
 			return rc;
 		}
 	}
 
 	// Close the device.
-	if (serial_close (device->port) == -1) {
+	if (device->serial->ops->close (device->serial->data) == -1) {
 		free (device);
 		return DC_STATUS_IO;
 	}
-- 
2.1.4

From ad0362033a03f66980a4064e0a24e472273a97a2 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <[email protected]>
Date: Fri, 26 Jun 2015 01:57:28 +0300
Subject: [PATCH 11/13] Implement custom open method for HW OSTC 3 family

Create a custom open method for HW OSTC3 family.
This method can be used to pass a reference to a dc_serial_t
structure. In this way the applications can implement their
own implementation for a serial communication and set their
callbacks for the basic serial functions.

Signed-off-by: Claudiu Olteanu <[email protected]>
---
 include/libdivecomputer/hw_ostc3.h |  3 +++
 src/hw_ostc3.c                     | 53 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/include/libdivecomputer/hw_ostc3.h b/include/libdivecomputer/hw_ostc3.h
index 047401b..0056f29 100644
--- a/include/libdivecomputer/hw_ostc3.h
+++ b/include/libdivecomputer/hw_ostc3.h
@@ -39,6 +39,9 @@ dc_status_t
 hw_ostc3_device_open (dc_device_t **device, dc_context_t *context, const char *name);
 
 dc_status_t
+hw_ostc3_device_custom_open (dc_device_t **device, dc_context_t *context, dc_serial_t *serial);
+
+dc_status_t
 hw_ostc3_device_version (dc_device_t *device, unsigned char data[], unsigned int size);
 
 dc_status_t
diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c
index 305bb80..a631ed6 100644
--- a/src/hw_ostc3.c
+++ b/src/hw_ostc3.c
@@ -306,6 +306,59 @@ hw_ostc3_device_open (dc_device_t **out, dc_context_t *context, const char *name
 }
 
 
+dc_status_t
+hw_ostc3_device_custom_open (dc_device_t **out, dc_context_t *context, dc_serial_t *serial)
+{
+	if (out == NULL)
+		return DC_STATUS_INVALIDARGS;
+
+	// Allocate memory.
+	hw_ostc3_device_t *device = (hw_ostc3_device_t *) malloc (sizeof (hw_ostc3_device_t));
+	if (device == NULL) {
+		ERROR (context, "Failed to allocate memory.");
+		return DC_STATUS_NOMEMORY;
+	}
+
+	// Initialize the base class.
+	device_init (&device->base, context, &hw_ostc3_device_vtable);
+
+	// Set the default values.
+	memset (device->fingerprint, 0, sizeof (device->fingerprint));
+
+	// Set the serial reference
+	device->serial = serial;
+
+	if (serial->type == DC_TRANSPORT_SERIAL) {
+		// Set the serial communication protocol (115200 8N1).
+		int rc = serial_configure (device->serial->data, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
+		if (rc == -1) {
+			ERROR (context, "Failed to set the terminal attributes.");
+			device->serial->ops->close (device->serial->data);
+			free (device);
+			return DC_STATUS_IO;
+		}
+	}
+
+	// Set the timeout for receiving data (3000ms).
+	if (serial_set_timeout (device->serial->data, 3000) == -1) {
+		ERROR (context, "Failed to set the timeout.");
+		device->serial->ops->close (device->serial->data);
+		free (device);
+		return DC_STATUS_IO;
+	}
+
+	// Make sure everything is in a sane state.
+	serial_sleep (device->serial->data, 300);
+	device->serial->ops->flush (device->serial->data, SERIAL_QUEUE_BOTH);
+
+	device->state = OPEN;
+
+	*out = (dc_device_t *) device;
+
+	return DC_STATUS_SUCCESS;
+}
+
+
 static dc_status_t
 hw_ostc3_device_init_download (hw_ostc3_device_t *device)
 {
-- 
2.1.4

From 2f9db8da10d27462e8884e23abcf3c83507aa9d5 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <[email protected]>
Date: Fri, 26 Jun 2015 02:05:53 +0300
Subject: [PATCH 12/13] Implement custom open method for HW OSTC family

Create a custom open method for HW OSTC family.
This method can be used to pass a reference to a dc_serial_t
structure. In this way the applications can implement their
own implementation for a serial communication and set
their callbacks for the basic serial functions.

Signed-off-by: Claudiu Olteanu <[email protected]>
---
 include/libdivecomputer/hw_ostc.h |  3 +++
 src/hw_ostc.c                     | 50 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+)

diff --git a/include/libdivecomputer/hw_ostc.h b/include/libdivecomputer/hw_ostc.h
index 52ef81b..8b1e412 100644
--- a/include/libdivecomputer/hw_ostc.h
+++ b/include/libdivecomputer/hw_ostc.h
@@ -45,6 +45,9 @@ dc_status_t
 hw_ostc_device_open (dc_device_t **device, dc_context_t *context, const char *name);
 
 dc_status_t
+hw_ostc_device_custom_open (dc_device_t **device, dc_context_t *context, dc_serial_t *serial);
+
+dc_status_t
 hw_ostc_device_md2hash (dc_device_t *device, unsigned char data[], unsigned int size);
 
 dc_status_t
diff --git a/src/hw_ostc.c b/src/hw_ostc.c
index ee7e17e..5618510 100644
--- a/src/hw_ostc.c
+++ b/src/hw_ostc.c
@@ -176,6 +176,56 @@ hw_ostc_device_open (dc_device_t **out, dc_context_t *context, const char *name)
 	return DC_STATUS_SUCCESS;
 }
 
+dc_status_t
+hw_ostc_device_custom_open (dc_device_t **out, dc_context_t *context, dc_serial_t *serial)
+{
+	if (out == NULL)
+		return DC_STATUS_INVALIDARGS;
+
+	// Allocate memory.
+	hw_ostc_device_t *device = (hw_ostc_device_t *) malloc (sizeof (hw_ostc_device_t));
+	if (device == NULL) {
+		ERROR (context, "Failed to allocate memory.");
+		return DC_STATUS_NOMEMORY;
+	}
+
+	// Initialize the base class.
+	device_init (&device->base, context, &hw_ostc_device_vtable);
+
+	// Set the default values.
+	memset (device->fingerprint, 0, sizeof (device->fingerprint));
+
+	// Set the serial reference
+	device->serial = serial;
+
+	if (serial->type == DC_TRANSPORT_SERIAL) {
+		// Set the serial communication protocol (115200 8N1).
+		int rc = serial_configure (serial->data, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
+		if (rc == -1) {
+			ERROR (context, "Failed to set the terminal attributes.");
+			serial->ops->close (serial->data);
+			free (device);
+			return DC_STATUS_IO;
+		}
+	}
+
+	// Set the timeout for receiving data.
+	if (serial_set_timeout (serial->data, 4000) == -1) {
+		ERROR (context, "Failed to set the timeout.");
+		serial->ops->close (serial->data);
+		free (device);
+		return DC_STATUS_IO;
+	}
+
+	// Make sure everything is in a sane state.
+	serial_sleep (serial->data, 100);
+	serial->ops->flush (serial->data, SERIAL_QUEUE_BOTH);
+
+	*out = (dc_device_t*) device;
+
+	return DC_STATUS_SUCCESS;
+}
+
 
 static dc_status_t
 hw_ostc_device_close (dc_device_t *abstract)
-- 
2.1.4

From 9a5cad60bbefc5d57028c31c185e9b615438afd7 Mon Sep 17 00:00:00 2001
From: Claudiu Olteanu <[email protected]>
Date: Fri, 26 Jun 2015 02:10:19 +0300
Subject: [PATCH 13/13] Implement custom device open method

This method can be used by external applications to open a
device and to pass their custom implementation for the
serial communication.

Signed-off-by: Claudiu Olteanu <[email protected]>
---
 include/libdivecomputer/device.h |  4 ++++
 src/device.c                     | 24 ++++++++++++++++++++++++
 2 files changed, 28 insertions(+)

diff --git a/include/libdivecomputer/device.h b/include/libdivecomputer/device.h
index 7ba4bd6..6691cf4 100644
--- a/include/libdivecomputer/device.h
+++ b/include/libdivecomputer/device.h
@@ -27,6 +27,7 @@
 #include "descriptor.h"
 #include "buffer.h"
 #include "datetime.h"
+#include "custom_serial.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -72,6 +73,9 @@ typedef int (*dc_dive_callback_t) (const unsigned char *data, unsigned int size,
 dc_status_t
 dc_device_open (dc_device_t **out, dc_context_t *context, dc_descriptor_t *descriptor, const char *name);
 
+dc_status_t
+dc_device_custom_open (dc_device_t **out, dc_context_t *context, dc_descriptor_t *descriptor, dc_serial_t *serial);
+
 dc_family_t
 dc_device_get_type (dc_device_t *device);
 
diff --git a/src/device.c b/src/device.c
index d95585d..9bd3dab 100644
--- a/src/device.c
+++ b/src/device.c
@@ -174,6 +174,30 @@ dc_device_open (dc_device_t **out, dc_context_t *context, dc_descriptor_t *descr
 	return rc;
 }
 
+dc_status_t
+dc_device_custom_open (dc_device_t **out, dc_context_t *context, dc_descriptor_t *descriptor, dc_serial_t *serial)
+{
+	dc_status_t rc = DC_STATUS_SUCCESS;
+	dc_device_t *device = NULL;
+
+	if (out == NULL || descriptor == NULL || serial == NULL)
+		return DC_STATUS_INVALIDARGS;
+
+	switch (dc_descriptor_get_type (descriptor)) {
+	case DC_FAMILY_HW_OSTC:
+		rc = hw_ostc_device_custom_open (&device, context, serial);
+		break;
+	case DC_FAMILY_HW_OSTC3:
+		rc = hw_ostc3_device_custom_open (&device, context, serial);
+		break;
+	default:
+		return DC_STATUS_INVALIDARGS;
+	}
+
+	*out = device;
+
+	return rc;
+}
 
 int
 dc_device_isinstance (dc_device_t *device, const dc_device_vtable_t *vtable)
-- 
2.1.4

_______________________________________________
subsurface mailing list
[email protected]
http://lists.subsurface-divelog.org/cgi-bin/mailman/listinfo/subsurface

Reply via email to