diff --git a/examples/reefnet_sensuspro_test.c b/examples/reefnet_sensuspro_test.c index 457cbda..b6c045c 100644 --- a/examples/reefnet_sensuspro_test.c +++ b/examples/reefnet_sensuspro_test.c @@ -1,7 +1,7 @@ #include // fopen, fwrite, fclose #include // time -#include "reefnet.h" +#include "reefnet_sensuspro.h" #include "utils.h" #define WARNING(expr) \ @@ -11,22 +11,22 @@ int test_dump_memory (const char* name, const char* filename) { - sensuspro *device = NULL; + device_t *device = NULL; unsigned char data[REEFNET_SENSUSPRO_MEMORY_SIZE] = {0}; unsigned char handshake[REEFNET_SENSUSPRO_HANDSHAKE_SIZE] = {0}; - message ("reefnet_sensuspro_open\n"); - int rc = reefnet_sensuspro_open (&device, name); - if (rc != REEFNET_SUCCESS) { + message ("reefnet_sensuspro_device_open\n"); + int rc = reefnet_sensuspro_device_open (&device, name); + if (rc != DEVICE_STATUS_SUCCESS) { WARNING ("Error opening serial port."); return rc; } - message ("reefnet_sensuspro_handshake\n"); - rc = reefnet_sensuspro_handshake (device, handshake, sizeof (handshake)); - if (rc != REEFNET_SUCCESS) { + message ("device_handshake\n"); + rc = device_handshake (device, handshake, sizeof (handshake)); + if (rc != DEVICE_STATUS_SUCCESS) { WARNING ("Cannot read handshake."); - reefnet_sensuspro_close (device); + device_close (device); return rc; } @@ -35,11 +35,11 @@ int test_dump_memory (const char* name, const char* filename) strftime (datetime, sizeof (datetime), "%Y-%m-%dT%H:%M:%SZ", gmtime (&now)); message ("time=%lu (%s)\n", (unsigned long)now, datetime); - message ("reefnet_sensuspro_read\n"); - rc = reefnet_sensuspro_read (device, data, sizeof (data)); - if (rc != REEFNET_SUCCESS) { + message ("device_download\n"); + rc = device_download (device, data, sizeof (data)); + if (rc != DEVICE_STATUS_SUCCESS) { WARNING ("Cannot read memory."); - reefnet_sensuspro_close (device); + device_close (device); return rc; } @@ -50,31 +50,35 @@ int test_dump_memory (const char* name, const char* filename) fclose (fp); } - message ("reefnet_sensuspro_close\n"); - rc = reefnet_sensuspro_close (device); - if (rc != REEFNET_SUCCESS) { + message ("device_close\n"); + rc = device_close (device); + if (rc != DEVICE_STATUS_SUCCESS) { WARNING ("Cannot close device."); return rc; } - return REEFNET_SUCCESS; + return DEVICE_STATUS_SUCCESS; } const char* errmsg (int rc) { switch (rc) { - case REEFNET_SUCCESS: + case DEVICE_STATUS_SUCCESS: return "Success"; - case REEFNET_ERROR: + case DEVICE_STATUS_UNSUPPORTED: + return "Unsupported operation"; + case DEVICE_STATUS_TYPE_MISMATCH: + return "Device type mismatch"; + case DEVICE_STATUS_ERROR: return "Generic error"; - case REEFNET_ERROR_IO: + case DEVICE_STATUS_IO: return "Input/output error"; - case REEFNET_ERROR_MEMORY: + case DEVICE_STATUS_MEMORY: return "Memory error"; - case REEFNET_ERROR_PROTOCOL: + case DEVICE_STATUS_PROTOCOL: return "Protocol error"; - case REEFNET_ERROR_TIMEOUT: + case DEVICE_STATUS_TIMEOUT: return "Timeout"; default: return "Unknown error"; diff --git a/src/device.h b/src/device.h index 5c94229..f3e1d18 100644 --- a/src/device.h +++ b/src/device.h @@ -10,7 +10,8 @@ typedef enum device_type_t { DEVICE_TYPE_SUUNTO_EON, DEVICE_TYPE_SUUNTO_VYPER, DEVICE_TYPE_SUUNTO_VYPER2, - DEVICE_TYPE_SUUNTO_D9 + DEVICE_TYPE_SUUNTO_D9, + DEVICE_TYPE_REEFNET_SENSUSPRO } device_type_t; typedef enum device_status_t { diff --git a/src/reefnet.h b/src/reefnet.h index ab9240b..df37904 100644 --- a/src/reefnet.h +++ b/src/reefnet.h @@ -1,6 +1,8 @@ #ifndef REEFNET_H #define REEFNET_H +#include "device.h" + #define REEFNET_SUCCESS 0 #define REEFNET_ERROR -1 #define REEFNET_ERROR_IO -2 @@ -8,8 +10,6 @@ #define REEFNET_ERROR_PROTOCOL -4 #define REEFNET_ERROR_TIMEOUT -5 -typedef void (*dive_callback_t) (const unsigned char *data, unsigned int size, void *userdata); - #include "reefnet_sensuspro.h" #include "reefnet_sensusultra.h" diff --git a/src/reefnet_sensuspro.c b/src/reefnet_sensuspro.c index 60bf921..29c2c3c 100644 --- a/src/reefnet_sensuspro.c +++ b/src/reefnet_sensuspro.c @@ -1,7 +1,8 @@ #include // memcmp, memcpy #include // malloc, free -#include "reefnet.h" +#include "device-private.h" +#include "reefnet_sensuspro.h" #include "serial.h" #include "utils.h" @@ -12,29 +13,44 @@ #define EXITCODE(rc) \ ( \ - rc == -1 ? REEFNET_ERROR_IO : REEFNET_ERROR_TIMEOUT \ + rc == -1 ? DEVICE_STATUS_IO : DEVICE_STATUS_TIMEOUT \ ) -struct sensuspro { +typedef struct reefnet_sensuspro_device_t reefnet_sensuspro_device_t; + +struct reefnet_sensuspro_device_t { + device_t base; struct serial *port; }; +static const device_backend_t reefnet_sensuspro_device_backend; -int -reefnet_sensuspro_open (sensuspro **out, const char* name) +static int +device_is_reefnet_sensuspro (device_t *abstract) +{ + if (abstract == NULL) + return 0; + + return abstract->backend == &reefnet_sensuspro_device_backend; +} + + +device_status_t +reefnet_sensuspro_device_open (device_t **out, const char* name) { if (out == NULL) - return REEFNET_ERROR; + return DEVICE_STATUS_ERROR; // Allocate memory. - struct sensuspro *device = malloc (sizeof (struct sensuspro)); + reefnet_sensuspro_device_t *device = malloc (sizeof (reefnet_sensuspro_device_t)); if (device == NULL) { WARNING ("Failed to allocate memory."); - return REEFNET_ERROR_MEMORY; + return DEVICE_STATUS_MEMORY; } // Set the default values. + device->base.backend = &reefnet_sensuspro_device_backend; device->port = NULL; // Open the device. @@ -42,7 +58,7 @@ reefnet_sensuspro_open (sensuspro **out, const char* name) if (rc == -1) { WARNING ("Failed to open the serial port."); free (device); - return REEFNET_ERROR_IO; + return DEVICE_STATUS_IO; } // Set the serial communication protocol (19200 8N1). @@ -51,7 +67,7 @@ reefnet_sensuspro_open (sensuspro **out, const char* name) WARNING ("Failed to set the terminal attributes."); serial_close (device->port); free (device); - return REEFNET_ERROR_IO; + return DEVICE_STATUS_IO; } // Set the timeout for receiving data (3000ms). @@ -59,34 +75,36 @@ reefnet_sensuspro_open (sensuspro **out, const char* name) WARNING ("Failed to set the timeout."); serial_close (device->port); free (device); - return REEFNET_ERROR_IO; + return DEVICE_STATUS_IO; } // Make sure everything is in a sane state. serial_flush (device->port, SERIAL_QUEUE_BOTH); - *out = device; + *out = (device_t*) device; - return REEFNET_SUCCESS; + return DEVICE_STATUS_SUCCESS; } -int -reefnet_sensuspro_close (sensuspro *device) +static device_status_t +reefnet_sensuspro_device_close (device_t *abstract) { - if (device == NULL) - return REEFNET_SUCCESS; + reefnet_sensuspro_device_t *device = (reefnet_sensuspro_device_t*) abstract; + + if (! device_is_reefnet_sensuspro (abstract)) + return DEVICE_STATUS_TYPE_MISMATCH; // Close the device. if (serial_close (device->port) == -1) { free (device); - return REEFNET_ERROR_IO; + return DEVICE_STATUS_IO; } // Free memory. free (device); - return REEFNET_SUCCESS; + return DEVICE_STATUS_SUCCESS; } @@ -136,11 +154,13 @@ reefnet_sensuspro_checksum (unsigned char *data, unsigned int size) } -int -reefnet_sensuspro_handshake (sensuspro *device, unsigned char *data, unsigned int size) +static device_status_t +reefnet_sensuspro_device_handshake (device_t *abstract, unsigned char *data, unsigned int size) { - if (device == NULL) - return REEFNET_ERROR; + reefnet_sensuspro_device_t *device = (reefnet_sensuspro_device_t*) abstract; + + if (! device_is_reefnet_sensuspro (abstract)) + return DEVICE_STATUS_TYPE_MISMATCH; // Assert a break condition. serial_set_break (device->port, 1); @@ -163,7 +183,7 @@ reefnet_sensuspro_handshake (sensuspro *device, unsigned char *data, unsigned in unsigned short ccrc = reefnet_sensuspro_checksum (handshake, REEFNET_SENSUSPRO_HANDSHAKE_SIZE); if (crc != ccrc) { WARNING ("Unexpected answer CRC."); - return REEFNET_ERROR_PROTOCOL; + return DEVICE_STATUS_PROTOCOL; } #ifndef NDEBUG @@ -184,20 +204,22 @@ reefnet_sensuspro_handshake (sensuspro *device, unsigned char *data, unsigned in memcpy (data, handshake, REEFNET_SENSUSPRO_HANDSHAKE_SIZE); } else { WARNING ("Insufficient buffer space available."); - return REEFNET_ERROR_MEMORY; + return DEVICE_STATUS_MEMORY; } serial_sleep (10); - return REEFNET_SUCCESS; + return DEVICE_STATUS_SUCCESS; } -int -reefnet_sensuspro_read (sensuspro *device, unsigned char *data, unsigned int size) +static device_status_t +reefnet_sensuspro_device_download (device_t *abstract, unsigned char *data, unsigned int size) { - if (device == NULL) - return REEFNET_ERROR; + reefnet_sensuspro_device_t *device = (reefnet_sensuspro_device_t*) abstract; + + if (! device_is_reefnet_sensuspro (abstract)) + return DEVICE_STATUS_TYPE_MISMATCH; unsigned char command = 0xB4; int rc = serial_write (device->port, &command, 1); @@ -228,28 +250,30 @@ reefnet_sensuspro_read (sensuspro *device, unsigned char *data, unsigned int siz unsigned short ccrc = reefnet_sensuspro_checksum (answer, REEFNET_SENSUSPRO_MEMORY_SIZE); if (crc != ccrc) { WARNING ("Unexpected answer CRC."); - return REEFNET_ERROR_PROTOCOL; + return DEVICE_STATUS_PROTOCOL; } if (size >= REEFNET_SENSUSPRO_MEMORY_SIZE) { memcpy (data, answer, REEFNET_SENSUSPRO_MEMORY_SIZE); } else { WARNING ("Insufficient buffer space available."); - return REEFNET_ERROR_MEMORY; + return DEVICE_STATUS_MEMORY; } - return REEFNET_SUCCESS; + return DEVICE_STATUS_SUCCESS; } -int -reefnet_sensuspro_write_interval (sensuspro *device, unsigned char interval) +device_status_t +reefnet_sensuspro_device_write_interval (device_t *abstract, unsigned char interval) { - if (device == NULL) - return REEFNET_ERROR; + reefnet_sensuspro_device_t *device = (reefnet_sensuspro_device_t*) abstract; + + if (! device_is_reefnet_sensuspro (abstract)) + return DEVICE_STATUS_TYPE_MISMATCH; if (interval < 1 || interval > 127) - return REEFNET_ERROR; + return DEVICE_STATUS_ERROR; unsigned char command = 0xB5; int rc = serial_write (device->port, &command, 1); @@ -266,11 +290,11 @@ reefnet_sensuspro_write_interval (sensuspro *device, unsigned char interval) return EXITCODE (rc); } - return REEFNET_SUCCESS; + return DEVICE_STATUS_SUCCESS; } -int +device_status_t reefnet_sensuspro_extract_dives (const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata) { const unsigned char header[4] = {0x00, 0x00, 0x00, 0x00}; @@ -301,7 +325,7 @@ reefnet_sensuspro_extract_dives (const unsigned char data[], unsigned int size, // Report an error if no stop marker was found. if (!found) - return REEFNET_ERROR; + return DEVICE_STATUS_ERROR; // Prepare for the next dive. previous = current; @@ -309,5 +333,17 @@ reefnet_sensuspro_extract_dives (const unsigned char data[], unsigned int size, } } - return REEFNET_SUCCESS; + return DEVICE_STATUS_SUCCESS; } + + +static const device_backend_t reefnet_sensuspro_device_backend = { + DEVICE_TYPE_REEFNET_SENSUSPRO, + reefnet_sensuspro_device_handshake, /* handshake */ + NULL, /* version */ + NULL, /* read */ + NULL, /* write */ + reefnet_sensuspro_device_download, /* download */ + NULL, /* foreach */ + reefnet_sensuspro_device_close /* close */ +}; diff --git a/src/reefnet_sensuspro.h b/src/reefnet_sensuspro.h index c195af2..022265c 100644 --- a/src/reefnet_sensuspro.h +++ b/src/reefnet_sensuspro.h @@ -5,22 +5,19 @@ extern "C" { #endif /* __cplusplus */ -typedef struct sensuspro sensuspro; +#include "device.h" #define REEFNET_SENSUSPRO_MEMORY_SIZE 56320 #define REEFNET_SENSUSPRO_HANDSHAKE_SIZE 10 -int reefnet_sensuspro_open (sensuspro **device, const char* name); +device_status_t +reefnet_sensuspro_device_open (device_t **device, const char* name); -int reefnet_sensuspro_close (sensuspro *device); +device_status_t +reefnet_sensuspro_write_interval (device_t *device, unsigned char interval); -int reefnet_sensuspro_handshake (sensuspro *device, unsigned char data[], unsigned int size); - -int reefnet_sensuspro_read (sensuspro *device, unsigned char data[], unsigned int size); - -int reefnet_sensuspro_write_interval (sensuspro *device, unsigned char interval); - -int reefnet_sensuspro_extract_dives (const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata); +device_status_t +reefnet_sensuspro_extract_dives (const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata); #ifdef __cplusplus }