Merge git://github.com/libdivecomputer/libdivecomputer into Subsurface-NG

Merge upstream libdivecomputer updates from Jef:

 - Add support for the Aqualung i550C

 - Update Ratio iX3M GPS naming and note that they support rfcomm

 - misc cleanups

* 'master' of git://github.com/libdivecomputer/libdivecomputer:
  Add support for the Aqualung i550C
  Enable bluetooth support for the Ratio iX3M GPS
  Update the naming of the Ratio iX3M GPS range
  Mark the string tables as constant
  Refactor the filter functions
This commit is contained in:
Linus Torvalds 2019-07-14 17:34:38 -07:00
commit ffbb472975
3 changed files with 134 additions and 70 deletions

View File

@ -28,6 +28,17 @@
#include "platform.h"
#define C_ARRAY_SIZE(array) (sizeof (array) / sizeof *(array))
#define C_ARRAY_ITEMSIZE(array) (sizeof *(array))
#define DC_FILTER_INTERNAL(key, values, isnullterminated, match) \
dc_filter_internal( \
key, \
values, \
C_ARRAY_SIZE(values) - isnullterminated, \
C_ARRAY_ITEMSIZE(values), \
match)
typedef int (*dc_match_t)(const void *, const void *);
static int dc_filter_uwatec (dc_transport_t transport, const void *userdata);
static int dc_filter_suunto (dc_transport_t transport, const void *userdata);
@ -36,6 +47,7 @@ static int dc_filter_hw (dc_transport_t transport, const void *userdata);
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 dc_status_t dc_descriptor_iterator_next (dc_iterator_t *iterator, void *item);
@ -228,6 +240,7 @@ static const dc_descriptor_t g_descriptors[] = {
{"Aqualung", "i300C", DC_FAMILY_OCEANIC_ATOM2, 0x4648, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, NULL},
{"Aqualung", "i100", DC_FAMILY_OCEANIC_ATOM2, 0x464E, DC_TRANSPORT_SERIAL, NULL},
{"Aqualung", "i770R", DC_FAMILY_OCEANIC_ATOM2, 0x4651, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, NULL},
{"Aqualung", "i550C", DC_FAMILY_OCEANIC_ATOM2, 0x4652, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, NULL},
{"Oceanic", "Geo 4.0", DC_FAMILY_OCEANIC_ATOM2, 0x4653, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, NULL},
/* Mares Nemo */
{"Mares", "Nemo", DC_FAMILY_MARES_NEMO, 0, DC_TRANSPORT_SERIAL, NULL},
@ -321,12 +334,12 @@ static const dc_descriptor_t g_descriptors[] = {
{"DiveSystem", "iDive Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x09, DC_TRANSPORT_SERIAL, NULL},
{"DiveSystem", "iDive X3M", DC_FAMILY_DIVESYSTEM_IDIVE, 0x0A, DC_TRANSPORT_SERIAL, NULL},
{"DiveSystem", "iDive Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x0B, DC_TRANSPORT_SERIAL, NULL},
{"Ratio", "iX3M Pro ", DC_FAMILY_DIVESYSTEM_IDIVE, 0x21, DC_TRANSPORT_SERIAL, NULL},
{"Ratio", "iX3M Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x22, DC_TRANSPORT_SERIAL, NULL},
{"Ratio", "iX3M Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x23, DC_TRANSPORT_SERIAL, NULL},
{"Ratio", "iX3M Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x24, DC_TRANSPORT_SERIAL, NULL},
{"Ratio", "iX3M Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x25, DC_TRANSPORT_SERIAL, NULL},
{"Ratio", "iX3M Fancy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x26, DC_TRANSPORT_SERIAL, NULL},
{"Ratio", "iX3M GPS Pro ", DC_FAMILY_DIVESYSTEM_IDIVE, 0x21, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_divesystem},
{"Ratio", "iX3M GPS Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x22, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_divesystem},
{"Ratio", "iX3M GPS Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x23, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_divesystem},
{"Ratio", "iX3M GPS Tech+",DC_FAMILY_DIVESYSTEM_IDIVE, 0x24, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_divesystem},
{"Ratio", "iX3M GPS Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x25, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_divesystem},
{"Ratio", "iX3M GPS Fancy",DC_FAMILY_DIVESYSTEM_IDIVE, 0x26, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_divesystem},
{"Ratio", "iX3M Pro Fancy",DC_FAMILY_DIVESYSTEM_IDIVE, 0x31, DC_TRANSPORT_SERIAL, NULL},
{"Ratio", "iX3M Pro Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x32, DC_TRANSPORT_SERIAL, NULL},
{"Ratio", "iX3M Pro Pro", DC_FAMILY_DIVESYSTEM_IDIVE, 0x33, DC_TRANSPORT_SERIAL, NULL},
@ -363,60 +376,89 @@ static const dc_descriptor_t g_descriptors[] = {
};
static int
dc_filter_internal_name (const char *name, const char *values[], size_t count)
dc_match_name (const void *key, const void *value)
{
if (name == NULL)
const char *k = (const char *) key;
const char *v = *(const char * const *) value;
return strcasecmp (k, v) == 0;
}
static int
dc_match_prefix (const void *key, const void *value)
{
const char *k = (const char *) key;
const char *v = *(const char * const *) value;
return strncasecmp (k, v, strlen (v)) == 0;
}
static int
dc_match_devname (const void *key, const void *value)
{
const char *k = (const char *) key;
const char *v = *(const char * const *) value;
return strncmp (k, v, strlen (v)) == 0;
}
static int
dc_match_usb (const void *key, const void *value)
{
const dc_usb_desc_t *k = (const dc_usb_desc_t *) key;
const dc_usb_desc_t *v = (const dc_usb_desc_t *) value;
return k->vid == v->vid && k->pid == v->pid;
}
static int
dc_match_number_with_prefix (const void *key, const void *value)
{
const char *str = (const char *) key;
const char *prefix = *(const char * const *) value;
size_t n = strlen (prefix);
if (strncmp (str, prefix, n) != 0) {
return 0;
}
while (str[n] != 0) {
const char c = str[n];
if (c < '0' || c > '9') {
return 0;
}
n++;
}
return 1;
}
static int
dc_filter_internal (const void *key, const void *values, size_t count, size_t size, dc_match_t match)
{
if (key == NULL)
return 0;
for (size_t i = 0; i < count; ++i) {
if (strcasecmp (name, values[i]) == 0) {
if (match (key, (const unsigned char *) values + i * size)) {
return 1;
}
}
return 0;
return count == 0;
}
static int
dc_filter_internal_usb (const dc_usb_desc_t *desc, const dc_usb_desc_t values[], size_t count)
{
if (desc == NULL)
return 0;
for (size_t i = 0; i < count; ++i) {
if (desc->vid == values[i].vid &&
desc->pid == values[i].pid) {
return 1;
}
}
return 0;
}
static int
dc_filter_internal_rfcomm (const char *name)
{
static const char *prefixes[] = {
static const char * const rfcomm[] = {
#if defined (__linux__)
"/dev/rfcomm",
#endif
NULL
};
if (name == NULL)
return 0;
for (size_t i = 0; prefixes[i] != NULL; ++i) {
if (strncmp (name, prefixes[i], strlen (prefixes[i])) == 0)
return 1;
}
return prefixes[0] == NULL;
}
};
static int dc_filter_uwatec (dc_transport_t transport, const void *userdata)
{
static const char *irda[] = {
static const char * const irda[] = {
"Aladin Smart Com",
"Aladin Smart Pro",
"Aladin Smart Tec",
@ -431,18 +473,18 @@ static int dc_filter_uwatec (dc_transport_t transport, const void *userdata)
{0x2e6c, 0x4201}, // G2 HUD
{0xc251, 0x2006}, // Aladin Square
};
static const char *bluetooth[] = {
static const char * const bluetooth[] = {
"G2",
"Aladin",
"HUD",
};
if (transport == DC_TRANSPORT_IRDA) {
return dc_filter_internal_name ((const char *) userdata, irda, C_ARRAY_SIZE(irda));
return DC_FILTER_INTERNAL (userdata, irda, 0, dc_match_name);
} else if (transport == DC_TRANSPORT_USBHID) {
return dc_filter_internal_usb ((const dc_usb_desc_t *) userdata, usbhid, C_ARRAY_SIZE(usbhid));
return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usb);
} else if (transport == DC_TRANSPORT_BLE) {
return dc_filter_internal_name ((const char *) userdata, bluetooth, C_ARRAY_SIZE(bluetooth));
return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_name);
}
return 1;
@ -455,18 +497,16 @@ static int dc_filter_suunto (dc_transport_t transport, const void *userdata)
{0x1493, 0x0033}, // Eon Core
{0x1493, 0x0035}, // D5
};
static const char *bluetooth[] = {
static const char * const bluetooth[] = {
"EON Steel",
"EON Core",
"Suunto D5",
};
if (transport == DC_TRANSPORT_USBHID) {
return dc_filter_internal_usb ((const dc_usb_desc_t *) userdata, usbhid, C_ARRAY_SIZE(usbhid));
return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usb);
} else if (transport == DC_TRANSPORT_BLE) {
// This won't work for the D5 - the serial number is in the name,
// and that's not how dc_filter_internal_name() works
return dc_filter_internal_name ((const char *) userdata, bluetooth, C_ARRAY_SIZE(bluetooth));
return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_prefix);
}
return 1;
@ -474,11 +514,15 @@ static int dc_filter_suunto (dc_transport_t transport, const void *userdata)
static int dc_filter_hw (dc_transport_t transport, const void *userdata)
{
static const char * const bluetooth[] = {
"OSTC",
"FROG",
};
if (transport == DC_TRANSPORT_BLUETOOTH || transport == DC_TRANSPORT_BLE) {
return strncasecmp ((const char *) userdata, "OSTC", 4) == 0 ||
strncasecmp ((const char *) userdata, "FROG", 4) == 0;
return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_prefix);
} else if (transport == DC_TRANSPORT_SERIAL) {
return dc_filter_internal_rfcomm ((const char *) userdata);
return DC_FILTER_INTERNAL (userdata, rfcomm, 1, dc_match_devname);
}
return 1;
@ -486,7 +530,7 @@ static int dc_filter_hw (dc_transport_t transport, const void *userdata)
static int dc_filter_shearwater (dc_transport_t transport, const void *userdata)
{
static const char *bluetooth[] = {
static const char * const bluetooth[] = {
"Predator",
"Petrel",
"Nerd",
@ -495,9 +539,9 @@ static int dc_filter_shearwater (dc_transport_t transport, const void *userdata)
};
if (transport == DC_TRANSPORT_BLUETOOTH || transport == DC_TRANSPORT_BLE) {
return dc_filter_internal_name ((const char *) userdata, bluetooth, C_ARRAY_SIZE(bluetooth));
return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_name);
} else if (transport == DC_TRANSPORT_SERIAL) {
return dc_filter_internal_rfcomm ((const char *) userdata);
return DC_FILTER_INTERNAL (userdata, rfcomm, 1, dc_match_devname);
}
return 1;
@ -505,14 +549,14 @@ static int dc_filter_shearwater (dc_transport_t transport, const void *userdata)
static int dc_filter_tecdiving (dc_transport_t transport, const void *userdata)
{
static const char *bluetooth[] = {
static const char * const bluetooth[] = {
"DiveComputer",
};
if (transport == DC_TRANSPORT_BLUETOOTH) {
return dc_filter_internal_name ((const char *) userdata, bluetooth, C_ARRAY_SIZE(bluetooth));
return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_name);
} else if (transport == DC_TRANSPORT_SERIAL) {
return dc_filter_internal_rfcomm ((const char *) userdata);
return DC_FILTER_INTERNAL (userdata, rfcomm, 1, dc_match_devname);
}
return 1;
@ -525,7 +569,7 @@ static int dc_filter_garmin (dc_transport_t transport, const void *userdata)
};
if (transport == DC_TRANSPORT_USBSTORAGE) {
return dc_filter_internal_usb ((const dc_usb_desc_t *) userdata, usbhid, C_ARRAY_SIZE(usbhid));
return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usb);
}
return 1;
@ -533,12 +577,25 @@ 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 const char *bluetooth[] = {
static const char * const bluetooth[] = {
"Mares bluelink pro",
};
if (transport == DC_TRANSPORT_BLE) {
return dc_filter_internal_name ((const char *) userdata, bluetooth, C_ARRAY_SIZE(bluetooth));
return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_name);
}
return 1;
}
static int dc_filter_divesystem (dc_transport_t transport, const void *userdata)
{
static const char * const bluetooth[] = {
"DS",
};
if (transport == DC_TRANSPORT_BLUETOOTH) {
return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_number_with_prefix);
}
return 1;

View File

@ -161,6 +161,7 @@ static const oceanic_common_version_t oceanic_oc1_version[] = {
{"OC1WATCH \0\0 1024"},
{"OCSWATCH \0\0 1024"},
{"AQUAI550 \0\0 1024"},
{"AQUA550C \0\0 1024"},
};
static const oceanic_common_version_t oceanic_oci_version[] = {

View File

@ -92,6 +92,7 @@
#define I300C 0x4648
#define I100 0x464E
#define I770R 0x4651
#define I550C 0x4652
#define GEO40 0x4653
#define NORMAL 0
@ -186,6 +187,8 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
parser->headersize = 5 * PAGESIZE;
} else if (model == PROPLUSX || model == GEO40) {
parser->headersize = 3 * PAGESIZE;
} else if (model == I550C) {
parser->headersize = 5 * PAGESIZE / 2;
}
parser->serial = serial;
@ -261,6 +264,7 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim
case A300AI:
case OCI:
case I550:
case I550C:
case VISION:
case XPAIR:
datetime->year = ((p[5] & 0xE0) >> 5) + ((p[7] & 0xE0) >> 2) + 2000;
@ -910,7 +914,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
} else {
unsigned int sign;
if (parser->model == DG03 || parser->model == PROPLUS3 ||
parser->model == I550)
parser->model == I550 || parser->model == I550C)
sign = (~data[offset + 5] & 0x04) >> 2;
else if (parser->model == VOYAGER2G || parser->model == AMPHOS ||
parser->model == AMPHOSAIR || parser->model == ZENAIR)
@ -942,7 +946,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
parser->model == ZENAIR ||parser->model == A300AI ||
parser->model == DG03 || parser->model == PROPLUS3 ||
parser->model == AMPHOSAIR || parser->model == I550 ||
parser->model == VISION || parser->model == XPAIR)
parser->model == VISION || parser->model == XPAIR ||
parser->model == I550C)
pressure = (((data[offset + 0] & 0x03) << 8) + data[offset + 1]) * 5;
else if (parser->model == TX1 || parser->model == A300CS ||
parser->model == VTX || parser->model == I750TC ||
@ -1012,7 +1017,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
decotime = array_uint16_le(data + offset + 6);
have_deco = 1;
} else if (parser->model == ATOM31 || parser->model == VISION ||
parser->model == XPAIR || parser->model == I550) {
parser->model == XPAIR || parser->model == I550 ||
parser->model == I550C) {
decostop = (data[offset + 5] & 0xF0) >> 4;
decotime = array_uint16_le(data + offset + 4) & 0x03FF;
have_deco = 1;
@ -1049,7 +1055,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
rbt = array_uint16_le(data + offset + 8) & 0x01FF;
have_rbt = 1;
} else if (parser->model == VISION || parser->model == XPAIR ||
parser->model == I550) {
parser->model == I550 || parser->model == I550C) {
rbt = array_uint16_le(data + offset + 6) & 0x03FF;
have_rbt = 1;
}