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:
Linus Torvalds 2019-08-15 14:46:38 -07:00
parent ffbb472975
commit 9812bf0828
10 changed files with 432 additions and 0 deletions

View File

@ -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[] = {

View File

@ -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

View File

@ -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"
>

View File

@ -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
View 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
View 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
View 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;
}

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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;
}