Deepblu Cosmiq+: Add skeleton code
This does nothing at all, but it adds all the core skeleton infrastructure for the Deepblu Cosmiq+ dive computer. Let's see if I can make sense of things and make it download anything. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
ffbb472975
commit
9812bf0828
@ -91,6 +91,7 @@ static const backend_table_t g_backends[] = {
|
||||
{"cochran", DC_FAMILY_COCHRAN_COMMANDER, 0},
|
||||
{"divecomputereu", DC_FAMILY_TECDIVING_DIVECOMPUTEREU, 0},
|
||||
{"descentmk1", DC_FAMILY_GARMIN, 0},
|
||||
{"cosmiq", DC_FAMILY_DEEPBLU, 0},
|
||||
};
|
||||
|
||||
static const transport_table_t g_transports[] = {
|
||||
|
||||
@ -110,6 +110,8 @@ typedef enum dc_family_t {
|
||||
DC_FAMILY_TECDIVING_DIVECOMPUTEREU = (15 << 16),
|
||||
/* Garmin */
|
||||
DC_FAMILY_GARMIN = (16 << 16),
|
||||
/* Deepblu */
|
||||
DC_FAMILY_DEEPBLU = (17 << 16),
|
||||
} dc_family_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -506,6 +506,14 @@
|
||||
RelativePath="..\src\garmin_parser.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\deepblu.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\deepblu_parser.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\timer.c"
|
||||
>
|
||||
@ -852,6 +860,10 @@
|
||||
RelativePath="..\src\garmin.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\deepblu.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\timer.h"
|
||||
>
|
||||
|
||||
@ -73,6 +73,7 @@ libdivecomputer_la_SOURCES = \
|
||||
cochran_commander.h cochran_commander.c cochran_commander_parser.c \
|
||||
tecdiving_divecomputereu.h tecdiving_divecomputereu.c tecdiving_divecomputereu_parser.c \
|
||||
garmin.h garmin.c garmin_parser.c \
|
||||
deepblu.h deepblu.c deepblu_parser.c \
|
||||
socket.h socket.c \
|
||||
irda.c \
|
||||
usbhid.c \
|
||||
|
||||
110
src/deepblu.c
Normal file
110
src/deepblu.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Deepblu Cosmiq+ downloading
|
||||
*
|
||||
* Copyright (C) 2019 Linus Torvalds
|
||||
*
|
||||
* 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 <string.h>
|
||||
|
||||
#include "deepblu.h"
|
||||
#include "context-private.h"
|
||||
#include "device-private.h"
|
||||
#include "array.h"
|
||||
|
||||
typedef struct deepblu_device_t {
|
||||
dc_device_t base;
|
||||
dc_iostream_t *iostream;
|
||||
unsigned char fingerprint[8];
|
||||
} deepblu_device_t;
|
||||
|
||||
static dc_status_t deepblu_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
|
||||
static dc_status_t deepblu_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata);
|
||||
static dc_status_t deepblu_device_close (dc_device_t *abstract);
|
||||
|
||||
static const dc_device_vtable_t deepblu_device_vtable = {
|
||||
sizeof(deepblu_device_t),
|
||||
DC_FAMILY_DEEPBLU,
|
||||
deepblu_device_set_fingerprint, /* set_fingerprint */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
NULL, /* dump */
|
||||
deepblu_device_foreach, /* foreach */
|
||||
NULL, /* timesync */
|
||||
deepblu_device_close, /* close */
|
||||
};
|
||||
|
||||
dc_status_t
|
||||
deepblu_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t *iostream)
|
||||
{
|
||||
deepblu_device_t *device;
|
||||
|
||||
if (out == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
device = (deepblu_device_t *) dc_device_allocate (context, &deepblu_device_vtable);
|
||||
if (device == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
// Set the default values.
|
||||
device->iostream = iostream;
|
||||
memset(device->fingerprint, 0, sizeof(device->fingerprint));
|
||||
|
||||
*out = (dc_device_t *) device;
|
||||
|
||||
ERROR (context, "Deepblu Cosmiq+ open called");
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
deepblu_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size)
|
||||
{
|
||||
deepblu_device_t *device = (deepblu_device_t *)abstract;
|
||||
|
||||
if (size && size != sizeof (device->fingerprint))
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
if (size)
|
||||
memcpy (device->fingerprint, data, sizeof (device->fingerprint));
|
||||
else
|
||||
memset (device->fingerprint, 0, sizeof (device->fingerprint));
|
||||
|
||||
ERROR (device->base.context, "Deepblu Cosmiq+ set_fingerprint called");
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
deepblu_device_close (dc_device_t *abstract)
|
||||
{
|
||||
deepblu_device_t *device = (deepblu_device_t *) abstract;
|
||||
|
||||
ERROR (device->base.context, "Deepblu Cosmiq+ device close called");
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
deepblu_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata)
|
||||
{
|
||||
deepblu_device_t *device = (deepblu_device_t *) abstract;
|
||||
|
||||
ERROR (device->base.context, "Deepblu Cosmiq+ device_foreach called");
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
43
src/deepblu.h
Normal file
43
src/deepblu.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Deepblu Cosmiq+ downloading/parsing
|
||||
*
|
||||
* Copyright (C) 2018 Linus Torvalds
|
||||
*
|
||||
* 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 DEEPBLU_H
|
||||
#define DEEPBLU_H
|
||||
|
||||
#include <libdivecomputer/context.h>
|
||||
#include <libdivecomputer/iostream.h>
|
||||
#include <libdivecomputer/device.h>
|
||||
#include <libdivecomputer/parser.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
dc_status_t
|
||||
deepblu_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
deepblu_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* DEEPBLU_H */
|
||||
240
src/deepblu_parser.c
Normal file
240
src/deepblu_parser.c
Normal file
@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Deeplu Cosmiq+ parsing
|
||||
*
|
||||
* Copyright (C) 2019 Linus Torvalds
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "deepblu.h"
|
||||
#include "context-private.h"
|
||||
#include "parser-private.h"
|
||||
#include "array.h"
|
||||
|
||||
#define C_ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
|
||||
|
||||
#define MAXFIELDS 128
|
||||
|
||||
struct msg_desc;
|
||||
|
||||
#define MAXTYPE 16
|
||||
#define MAXGASES 16
|
||||
#define MAXSTRINGS 32
|
||||
|
||||
typedef struct deepblu_parser_t {
|
||||
dc_parser_t base;
|
||||
|
||||
dc_sample_callback_t callback;
|
||||
void *userdata;
|
||||
|
||||
// Field cache
|
||||
struct {
|
||||
unsigned int initialized;
|
||||
|
||||
// dc_get_field() data
|
||||
unsigned int DIVETIME;
|
||||
double MAXDEPTH;
|
||||
double AVGDEPTH;
|
||||
unsigned int GASMIX_COUNT;
|
||||
dc_salinity_t SALINITY;
|
||||
dc_gasmix_t gasmix[MAXGASES];
|
||||
|
||||
dc_field_string_t strings[MAXSTRINGS];
|
||||
} cache;
|
||||
} deepblu_parser_t;
|
||||
|
||||
// I *really* need to make this generic
|
||||
static void add_string(deepblu_parser_t *deepblu, const char *desc, const char *data);
|
||||
static void add_string_fmt(deepblu_parser_t *deepblu, const char *desc, const char *fmt, ...);
|
||||
|
||||
/*
|
||||
* Macro to make it easy to set DC_FIELD_xyz values
|
||||
*/
|
||||
#define ASSIGN_FIELD(name, value) do { \
|
||||
deepblu->cache.initialized |= 1u << DC_FIELD_##name; \
|
||||
deepblu->cache.name = (value); \
|
||||
} while (0)
|
||||
|
||||
|
||||
static dc_status_t deepblu_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t deepblu_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t deepblu_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t deepblu_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
|
||||
static const dc_parser_vtable_t deepblu_parser_vtable = {
|
||||
sizeof(deepblu_parser_t),
|
||||
DC_FAMILY_DEEPBLU,
|
||||
deepblu_parser_set_data, /* set_data */
|
||||
deepblu_parser_get_datetime, /* datetime */
|
||||
deepblu_parser_get_field, /* fields */
|
||||
deepblu_parser_samples_foreach, /* samples_foreach */
|
||||
NULL /* destroy */
|
||||
};
|
||||
|
||||
dc_status_t
|
||||
deepblu_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
{
|
||||
deepblu_parser_t *parser = NULL;
|
||||
|
||||
if (out == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (deepblu_parser_t *) dc_parser_allocate (context, &deepblu_parser_vtable);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
*out = (dc_parser_t *) parser;
|
||||
|
||||
ERROR (context, "Deepblu Cosmiq+ parser_create() called");
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME! This should all be generic.
|
||||
*
|
||||
* Now it's just copied between all the different
|
||||
* dive computers that support the strings..
|
||||
*/
|
||||
static void add_string(deepblu_parser_t *deepblu, const char *desc, const char *value)
|
||||
{
|
||||
int i;
|
||||
|
||||
deepblu->cache.initialized |= 1 << DC_FIELD_STRING;
|
||||
for (i = 0; i < MAXSTRINGS; i++) {
|
||||
dc_field_string_t *str = deepblu->cache.strings+i;
|
||||
if (str->desc)
|
||||
continue;
|
||||
str->desc = desc;
|
||||
str->value = strdup(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void add_string_fmt(deepblu_parser_t *deepblu, const char *desc, const char *fmt, ...)
|
||||
{
|
||||
char buffer[256];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
buffer[sizeof(buffer)-1] = 0;
|
||||
(void) vsnprintf(buffer, sizeof(buffer)-1, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
add_string(deepblu, desc, buffer);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
deepblu_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
deepblu_parser_t *deepblu = (deepblu_parser_t *) abstract;
|
||||
|
||||
deepblu->callback = NULL;
|
||||
deepblu->userdata = NULL;
|
||||
memset(&deepblu->cache, 0, sizeof(deepblu->cache));
|
||||
|
||||
ERROR (abstract->context, "Deepblu Cosmiq+ parser_set_data() called");
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
deepblu_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
deepblu_parser_t *deepblu = (deepblu_parser_t *) abstract;
|
||||
|
||||
ERROR (abstract->context, "Deepblu Cosmiq+ parser_get_datetime() called");
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static dc_status_t get_string_field(dc_field_string_t *strings, unsigned idx, dc_field_string_t *value)
|
||||
{
|
||||
if (idx < MAXSTRINGS) {
|
||||
dc_field_string_t *res = strings+idx;
|
||||
if (res->desc && res->value) {
|
||||
*value = *res;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
// Ugly define thing makes the code much easier to read
|
||||
// I'd love to use __typeof__, but that's a gcc'ism
|
||||
#define field_value(p, NAME) \
|
||||
(memcpy((p), &deepblu->cache.NAME, sizeof(deepblu->cache.NAME)), DC_STATUS_SUCCESS)
|
||||
// Hacky hack hack
|
||||
#define GASMIX gasmix[flags]
|
||||
|
||||
static dc_status_t
|
||||
deepblu_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value)
|
||||
{
|
||||
deepblu_parser_t *deepblu = (deepblu_parser_t *) abstract;
|
||||
|
||||
if (!value)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
/* This whole sequence should be standardized */
|
||||
if (!(deepblu->cache.initialized & (1 << type)))
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
|
||||
switch (type) {
|
||||
case DC_FIELD_DIVETIME:
|
||||
return field_value(value, DIVETIME);
|
||||
case DC_FIELD_MAXDEPTH:
|
||||
return field_value(value, MAXDEPTH);
|
||||
case DC_FIELD_AVGDEPTH:
|
||||
return field_value(value, AVGDEPTH);
|
||||
case DC_FIELD_GASMIX_COUNT:
|
||||
case DC_FIELD_TANK_COUNT:
|
||||
return field_value(value, GASMIX_COUNT);
|
||||
case DC_FIELD_GASMIX:
|
||||
if (flags >= MAXGASES)
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
return field_value(value, GASMIX);
|
||||
case DC_FIELD_SALINITY:
|
||||
return field_value(value, SALINITY);
|
||||
case DC_FIELD_ATMOSPHERIC:
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
case DC_FIELD_DIVEMODE:
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
case DC_FIELD_TANK:
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
case DC_FIELD_STRING:
|
||||
return get_string_field(deepblu->cache.strings, flags, (dc_field_string_t *)value);
|
||||
default:
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
deepblu_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
|
||||
{
|
||||
deepblu_parser_t *deepblu = (deepblu_parser_t *) abstract;
|
||||
|
||||
deepblu->callback = callback;
|
||||
deepblu->userdata = userdata;
|
||||
|
||||
ERROR (abstract->context, "Deepblu Cosmiq+ samples_foreach() called");
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
@ -48,6 +48,7 @@ static int dc_filter_tecdiving (dc_transport_t transport, const void *userdata);
|
||||
static int dc_filter_garmin (dc_transport_t transport, const void *userdata);
|
||||
static int dc_filter_mares (dc_transport_t transport, const void *userdata);
|
||||
static int dc_filter_divesystem (dc_transport_t transport, const void *userdata);
|
||||
static int dc_filter_deepblu (dc_transport_t transport, const void *userdata);
|
||||
|
||||
static dc_status_t dc_descriptor_iterator_next (dc_iterator_t *iterator, void *item);
|
||||
|
||||
@ -373,6 +374,8 @@ static const dc_descriptor_t g_descriptors[] = {
|
||||
{"Tecdiving", "DiveComputer.eu", DC_FAMILY_TECDIVING_DIVECOMPUTEREU, 0, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_tecdiving},
|
||||
/* Garmin */
|
||||
{"Garmin", "Descent Mk1", DC_FAMILY_GARMIN, 2859, DC_TRANSPORT_USBSTORAGE, dc_filter_garmin},
|
||||
/* Deepblu */
|
||||
{"Deepblu", "Cosmiq+", DC_FAMILY_DEEPBLU, 0, DC_TRANSPORT_BLE, dc_filter_deepblu},
|
||||
};
|
||||
|
||||
static int
|
||||
@ -601,6 +604,19 @@ static int dc_filter_divesystem (dc_transport_t transport, const void *userdata)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dc_filter_deepblu (dc_transport_t transport, const void *userdata)
|
||||
{
|
||||
static const char * const bluetooth[] = {
|
||||
"COSMIQ",
|
||||
};
|
||||
|
||||
if (transport == DC_TRANSPORT_BLE) {
|
||||
return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_name);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_descriptor_iterator (dc_iterator_t **out)
|
||||
{
|
||||
|
||||
@ -58,6 +58,7 @@
|
||||
#include "cochran_commander.h"
|
||||
#include "tecdiving_divecomputereu.h"
|
||||
#include "garmin.h"
|
||||
#include "deepblu.h"
|
||||
|
||||
#include "device-private.h"
|
||||
#include "context-private.h"
|
||||
@ -215,6 +216,9 @@ dc_device_open (dc_device_t **out, dc_context_t *context, dc_descriptor_t *descr
|
||||
case DC_FAMILY_GARMIN:
|
||||
rc = garmin_device_open (&device, context, iostream);
|
||||
break;
|
||||
case DC_FAMILY_DEEPBLU:
|
||||
rc = deepblu_device_open (&device, context, iostream);
|
||||
break;
|
||||
default:
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
@ -176,6 +176,9 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t fa
|
||||
case DC_FAMILY_GARMIN:
|
||||
rc = garmin_parser_create (&parser, context);
|
||||
break;
|
||||
case DC_FAMILY_DEEPBLU:
|
||||
rc = deepblu_parser_create (&parser, context);
|
||||
break;
|
||||
default:
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user