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

Merge with upstream.

* git://github.com/libdivecomputer/libdivecomputer:
  Simplify the conditional compilation
  Disable some Windows specific compiler warnings
  Use SDP to auto-detect the rfcomm port number
  Use the actual IrDA device names
  Use the correct data type for the temperature
  Disable O2 sensors with default calibration values
  Add support for the Seac Jack
  Check for memory allocation errors
  Erase the buffer before calling the vtable function
  Replace hardcoded size with the sizeof operator
  Use the correct model number for the Shearwater Nerd 2
This commit is contained in:
Linus Torvalds 2018-01-31 10:57:02 -08:00
commit fb0d0b269e
37 changed files with 260 additions and 147 deletions

View File

@ -195,6 +195,11 @@ AX_APPEND_COMPILE_FLAGS([ \
-Wno-unused-parameter \
])
# Windows specific compiler options.
AS_IF([test "$os_win32" = "yes"], [
AX_APPEND_COMPILE_FLAGS([-Wno-pedantic-ms-format])
])
# Versioning.
AC_SUBST([DC_VERSION],[dc_version])
AC_SUBST([DC_VERSION_MAJOR],[dc_version_major])

View File

@ -30,6 +30,7 @@
#ifdef _WIN32
#ifdef HAVE_WS2BTH_H
#define BLUETOOTH
#include <initguid.h>
#include <ws2bth.h>
#endif
#else
@ -39,6 +40,8 @@
#include <bluetooth/rfcomm.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
#endif
#endif
@ -105,6 +108,89 @@ dc_address_set (bdaddr_t *ba, dc_bluetooth_address_t address)
shift += 8;
}
}
static dc_status_t
dc_bluetooth_sdp (uint8_t *port, dc_context_t *context, const bdaddr_t *ba)
{
dc_status_t status = DC_STATUS_SUCCESS;
sdp_session_t *session = NULL;
sdp_list_t *search = NULL, *attrid = NULL;
sdp_list_t *records = NULL;
uint8_t channel = 0;
// Connect to the SDP server on the remote device.
session = sdp_connect (BDADDR_ANY, ba, SDP_RETRY_IF_BUSY);
if (session == NULL) {
s_errcode_t errcode = S_ERRNO;
SYSERROR (context, errcode);
status = dc_socket_syserror(errcode);
goto error;
}
// Specify the UUID of the serial port service with all attributes.
uuid_t uuid = {0};
uint32_t range = 0x0000FFFF;
sdp_uuid16_create (&uuid, SERIAL_PORT_SVCLASS_ID);
search = sdp_list_append (NULL, &uuid);
attrid = sdp_list_append (NULL, &range);
if (search == NULL || attrid == NULL) {
s_errcode_t errcode = S_ERRNO;
SYSERROR (context, errcode);
status = dc_socket_syserror(errcode);
goto error;
}
// Get a list of the service records with their attributes.
if (sdp_service_search_attr_req (session, search, SDP_ATTR_REQ_RANGE, attrid, &records) != 0) {
s_errcode_t errcode = S_ERRNO;
SYSERROR (context, errcode);
status = dc_socket_syserror(errcode);
goto error;
}
// Go through each of the service records.
for (sdp_list_t *r = records; r; r = r->next ) {
sdp_record_t *record = (sdp_record_t *) r->data;
// Get a list of the protocol sequences.
sdp_list_t *protos = NULL;
if (sdp_get_access_protos (record, &protos) != 0 ) {
s_errcode_t errcode = S_ERRNO;
SYSERROR (context, errcode);
status = dc_socket_syserror(errcode);
goto error;
}
// Get the rfcomm port number.
int ch = sdp_get_proto_port (protos, RFCOMM_UUID);
sdp_list_foreach (protos, (sdp_list_func_t) sdp_list_free, NULL);
sdp_list_free (protos, NULL);
if (ch > 0) {
channel = ch;
break;
}
}
if (channel == 0) {
ERROR (context, "No serial port service found!");
status = DC_STATUS_IO;
goto error;
}
INFO (context, "SDP: channel=%u", channel);
*port = channel;
error:
sdp_list_free (records, (sdp_free_func_t) sdp_record_free);
sdp_list_free (attrid, NULL);
sdp_list_free (search, NULL);
sdp_close (session);
return status;
}
#endif
#endif
@ -298,12 +384,23 @@ dc_bluetooth_connect (dc_iostream_t *abstract, dc_bluetooth_address_t address, u
sa.addressFamily = AF_BTH;
sa.btAddr = address;
sa.port = port;
memset(&sa.serviceClassId, 0, sizeof(sa.serviceClassId));
if (port == 0) {
sa.serviceClassId = SerialPortServiceClass_UUID;
} else {
memset(&sa.serviceClassId, 0, sizeof(sa.serviceClassId));
}
#else
struct sockaddr_rc sa;
sa.rc_family = AF_BLUETOOTH;
sa.rc_channel = port;
dc_address_set (&sa.rc_bdaddr, address);
if (port == 0) {
dc_status_t rc = dc_bluetooth_sdp (&sa.rc_channel, abstract->context, &sa.rc_bdaddr);
if (rc != DC_STATUS_SUCCESS) {
return rc;
}
} else {
sa.rc_channel = port;
}
#endif
return dc_socket_connect (&device->base, (struct sockaddr *) &sa, sizeof (sa));

View File

@ -152,13 +152,6 @@ citizen_aqualand_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
dc_status_t status = DC_STATUS_SUCCESS;
citizen_aqualand_device_t *device = (citizen_aqualand_device_t *) abstract;
// Erase the current contents of the buffer and
// pre-allocate the required amount of memory.
if (!dc_buffer_clear (buffer)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}
status = dc_iostream_set_dtr (device->iostream, 1);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to set the DTR line.");
@ -192,7 +185,10 @@ citizen_aqualand_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
return status;
}
dc_buffer_append(buffer, answer, sizeof (answer));
if (!dc_buffer_append(buffer, answer, sizeof (answer))) {
ERROR (abstract->context, "Insufficient buffer space available.");
return status;
}
// Send the command.
status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);

View File

@ -842,12 +842,6 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
unsigned int config_size = sizeof(config);
unsigned int size = device->layout->rb_profile_end - device->layout->rb_logbook_begin;
// Make sure buffer is good.
if (!dc_buffer_clear(buffer)) {
ERROR (abstract->context, "Uninitialized buffer.");
return DC_STATUS_INVALIDARGS;
}
// Reserve space
if (!dc_buffer_resize(buffer, size)) {
ERROR(abstract->context, "Insufficient buffer space available.");

View File

@ -474,19 +474,19 @@ cochran_commander_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
if (value) {
switch (type) {
case DC_FIELD_TEMPERATURE_SURFACE:
*((unsigned int*) value) = (data[layout->start_temp] - 32.0) / 1.8;
*((double *) value) = (data[layout->start_temp] - 32.0) / 1.8;
break;
case DC_FIELD_TEMPERATURE_MINIMUM:
if (data[layout->min_temp] == 0xFF)
return DC_STATUS_UNSUPPORTED;
*((unsigned int*) value) = (data[layout->min_temp] / 2.0 + 20 - 32) / 1.8;
*((double *) value) = (data[layout->min_temp] / 2.0 + 20 - 32) / 1.8;
break;
case DC_FIELD_TEMPERATURE_MAXIMUM:
if (layout->max_temp == UNSUPPORTED)
return DC_STATUS_UNSUPPORTED;
if (data[layout->max_temp] == 0xFF)
return DC_STATUS_UNSUPPORTED;
*((unsigned int*) value) = (data[layout->max_temp] / 2.0 + 20 - 32) / 1.8;
*((double *) value) = (data[layout->max_temp] / 2.0 + 20 - 32) / 1.8;
break;
case DC_FIELD_DIVETIME:
minutes = array_uint16_le(data + layout->divetime);

View File

@ -389,9 +389,8 @@ cressi_edy_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
{
cressi_edy_device_t *device = (cressi_edy_device_t *) abstract;
// Erase the current contents of the buffer and
// allocate the required amount of memory.
if (!dc_buffer_clear (buffer) || !dc_buffer_resize (buffer, device->layout->memsize)) {
// Allocate the required amount of memory.
if (!dc_buffer_resize (buffer, device->layout->memsize)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}

View File

@ -320,9 +320,8 @@ cressi_leonardo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
dc_status_t status = DC_STATUS_SUCCESS;
cressi_leonardo_device_t *device = (cressi_leonardo_device_t *) abstract;
// Erase the current contents of the buffer and
// pre-allocate the required amount of memory.
if (!dc_buffer_clear (buffer) || !dc_buffer_resize (buffer, SZ_MEMORY)) {
// Allocate the required amount of memory.
if (!dc_buffer_resize (buffer, SZ_MEMORY)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}

View File

@ -293,9 +293,9 @@ static const dc_descriptor_t g_descriptors[] = {
{"Shearwater", "Petrel", DC_FAMILY_SHEARWATER_PETREL, 3}, // BT // BLE
{"Shearwater", "Petrel 2", DC_FAMILY_SHEARWATER_PETREL, 3}, // BT // BLE
{"Shearwater", "Nerd", DC_FAMILY_SHEARWATER_PETREL, 4}, // BT
{"Shearwater", "Nerd 2", DC_FAMILY_SHEARWATER_PETREL, 4}, // BLE
{"Shearwater", "Perdix", DC_FAMILY_SHEARWATER_PETREL, 5}, // BT // BLE
{"Shearwater", "Perdix AI", DC_FAMILY_SHEARWATER_PETREL, 6}, // BLE
{"Shearwater", "Nerd 2", DC_FAMILY_SHEARWATER_PETREL, 7}, // BLE
/* Dive Rite NiTek Q */
{"Dive Rite", "NiTek Q", DC_FAMILY_DIVERITE_NITEKQ, 0},
/* Citizen Hyper Aqualand */
@ -322,6 +322,7 @@ static const dc_descriptor_t g_descriptors[] = {
{"Ratio", "iDive Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x42},
{"Ratio", "iDive Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x44},
{"Ratio", "iDive Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x45},
{"Seac", "Jack", DC_FAMILY_DIVESYSTEM_IDIVE, 0x1000},
/* Cochran Commander */
{"Cochran", "Commander TM", DC_FAMILY_COCHRAN_COMMANDER, 0}, // FTDI
{"Cochran", "Commander I", DC_FAMILY_COCHRAN_COMMANDER, 1}, // FTDI

View File

@ -316,6 +316,11 @@ dc_device_dump (dc_device_t *device, dc_buffer_t *buffer)
if (device->vtable->dump == NULL)
return DC_STATUS_UNSUPPORTED;
if (buffer == NULL)
return DC_STATUS_INVALIDARGS;
dc_buffer_clear (buffer);
return device->vtable->dump (device, buffer);
}

View File

@ -258,8 +258,8 @@ diverite_nitekq_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
dc_status_t rc = DC_STATUS_SUCCESS;
unsigned char packet[256] = {0};
// Erase the current contents of the buffer.
if (!dc_buffer_clear (buffer) || !dc_buffer_reserve (buffer, SZ_PACKET + SZ_MEMORY)) {
// Pre-allocate the required amount of memory.
if (!dc_buffer_reserve (buffer, SZ_PACKET + SZ_MEMORY)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}

View File

@ -493,7 +493,12 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
dc_buffer_clear(buffer);
dc_buffer_reserve(buffer, commands->header.size + commands->sample.size * nsamples);
dc_buffer_append(buffer, packet, commands->header.size);
if (!dc_buffer_append(buffer, packet, commands->header.size)) {
ERROR (abstract->context, "Insufficient buffer space available.");
dc_buffer_free(buffer);
return rc;
}
for (unsigned int j = 0; j < nsamples; j += commands->nsamples) {
unsigned int idx = j + 1;
@ -518,7 +523,11 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
progress.current = i * NSTEPS + STEP(j + n + 1, nsamples + 1);
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
dc_buffer_append(buffer, packet, commands->sample.size * n);
if (!dc_buffer_append(buffer, packet, commands->sample.size * n)) {
ERROR (abstract->context, "Insufficient buffer space available.");
dc_buffer_free(buffer);
return rc;
}
}
unsigned char *data = dc_buffer_get_data(buffer);

View File

@ -219,12 +219,6 @@ hw_ostc_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
dc_status_t status = DC_STATUS_SUCCESS;
hw_ostc_device_t *device = (hw_ostc_device_t*) abstract;
// Erase the current contents of the buffer.
if (!dc_buffer_clear (buffer)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}
// Enable progress notifications.
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
progress.maximum = SZ_HEADER + SZ_FW_NEW;
@ -593,7 +587,10 @@ hw_ostc_device_screenshot (dc_device_t *abstract, dc_buffer_t *buffer, hw_ostc_f
if (format == HW_OSTC_FORMAT_RAW) {
// Append the raw data to the output buffer.
dc_buffer_append (buffer, raw, nbytes);
if (!dc_buffer_append (buffer, raw, nbytes)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}
} else {
// Store the decompressed data in the output buffer.
for (unsigned int i = 0; i < count; ++i) {

View File

@ -1150,7 +1150,11 @@ hw_ostc3_firmware_readfile4 (dc_buffer_t *buffer, dc_context_t *context, const c
size_t n = 0;
unsigned char block[1024] = {0};
while ((n = fread (block, 1, sizeof (block), fp)) > 0) {
dc_buffer_append (buffer, block, n);
if (!dc_buffer_append (buffer, block, n)) {
ERROR (context, "Insufficient buffer space available.");
fclose (fp);
return DC_STATUS_NOMEMORY;
}
}
// Close the file.
@ -1555,12 +1559,6 @@ hw_ostc3_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
{
hw_ostc3_device_t *device = (hw_ostc3_device_t *) abstract;
// Erase the current contents of the buffer.
if (!dc_buffer_clear (buffer)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}
// Enable progress notifications.
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
progress.maximum = SZ_MEMORY;

View File

@ -263,13 +263,13 @@ dc_irda_connect_lsap (dc_iostream_t *abstract, unsigned int address, unsigned in
peer.irdaDeviceID[1] = (address >> 8) & 0xFF;
peer.irdaDeviceID[2] = (address >> 16) & 0xFF;
peer.irdaDeviceID[3] = (address >> 24) & 0xFF;
snprintf (peer.irdaServiceName, 25, "LSAP-SEL%u", lsap);
snprintf (peer.irdaServiceName, sizeof(peer.irdaServiceName), "LSAP-SEL%u", lsap);
#else
struct sockaddr_irda peer;
peer.sir_family = AF_IRDA;
peer.sir_addr = address;
peer.sir_lsap_sel = lsap;
memset (peer.sir_name, 0x00, 25);
memset (peer.sir_name, 0x00, sizeof(peer.sir_name));
#endif
return dc_socket_connect (&device->base, (struct sockaddr *) &peer, sizeof (peer));

View File

@ -219,9 +219,8 @@ mares_darwin_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
assert (device->layout != NULL);
// Erase the current contents of the buffer and
// allocate the required amount of memory.
if (!dc_buffer_clear (buffer) || !dc_buffer_resize (buffer, device->layout->memsize)) {
// Allocate the required amount of memory.
if (!dc_buffer_resize (buffer, device->layout->memsize)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}

View File

@ -403,9 +403,8 @@ mares_iconhd_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
{
mares_iconhd_device_t *device = (mares_iconhd_device_t *) abstract;
// Erase the current contents of the buffer and
// pre-allocate the required amount of memory.
if (!dc_buffer_clear (buffer) || !dc_buffer_resize (buffer, device->layout->memsize)) {
// Allocate the required amount of memory.
if (!dc_buffer_resize (buffer, device->layout->memsize)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}

View File

@ -193,9 +193,8 @@ mares_nemo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
dc_status_t status = DC_STATUS_SUCCESS;
mares_nemo_device_t *device = (mares_nemo_device_t *) abstract;
// Erase the current contents of the buffer and
// pre-allocate the required amount of memory.
if (!dc_buffer_clear (buffer) || !dc_buffer_reserve (buffer, MEMORYSIZE)) {
// Pre-allocate the required amount of memory.
if (!dc_buffer_reserve (buffer, MEMORYSIZE)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}

View File

@ -224,9 +224,8 @@ mares_puck_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
assert (device->layout != NULL);
// Erase the current contents of the buffer and
// allocate the required amount of memory.
if (!dc_buffer_clear (buffer) || !dc_buffer_resize (buffer, device->layout->memsize)) {
// Allocate the required amount of memory.
if (!dc_buffer_resize (buffer, device->layout->memsize)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}

View File

@ -156,9 +156,8 @@ oceanic_common_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
assert (device != NULL);
assert (device->layout != NULL);
// Erase the current contents of the buffer and
// allocate the required amount of memory.
if (!dc_buffer_clear (buffer) || !dc_buffer_resize (buffer, device->layout->memsize)) {
// Allocate the required amount of memory.
if (!dc_buffer_resize (buffer, device->layout->memsize)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}

View File

@ -279,9 +279,8 @@ reefnet_sensus_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
dc_status_t status = DC_STATUS_SUCCESS;
reefnet_sensus_device_t *device = (reefnet_sensus_device_t*) abstract;
// Erase the current contents of the buffer and
// pre-allocate the required amount of memory.
if (!dc_buffer_clear (buffer) || !dc_buffer_reserve (buffer, SZ_MEMORY)) {
// Pre-allocate the required amount of memory.
if (!dc_buffer_reserve (buffer, SZ_MEMORY)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}

View File

@ -271,9 +271,8 @@ reefnet_sensuspro_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
dc_status_t status = DC_STATUS_SUCCESS;
reefnet_sensuspro_device_t *device = (reefnet_sensuspro_device_t*) abstract;
// Erase the current contents of the buffer and
// pre-allocate the required amount of memory.
if (!dc_buffer_clear (buffer) || !dc_buffer_reserve (buffer, SZ_MEMORY)) {
// Pre-allocate the required amount of memory.
if (!dc_buffer_reserve (buffer, SZ_MEMORY)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}

View File

@ -379,9 +379,8 @@ reefnet_sensusultra_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
{
reefnet_sensusultra_device_t *device = (reefnet_sensusultra_device_t*) abstract;
// Erase the current contents of the buffer and
// pre-allocate the required amount of memory.
if (!dc_buffer_clear (buffer) || !dc_buffer_reserve (buffer, SZ_MEMORY)) {
// Pre-allocate the required amount of memory.
if (!dc_buffer_reserve (buffer, SZ_MEMORY)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}

View File

@ -307,12 +307,6 @@ scubapro_g2_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
scubapro_g2_device_t *device = (scubapro_g2_device_t*) abstract;
dc_status_t rc = DC_STATUS_SUCCESS;
// Erase the current contents of the buffer.
if (!dc_buffer_clear (buffer)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}
// Enable progress notifications.
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress);

View File

@ -38,6 +38,7 @@ extern "C" {
#define NERD 4
#define PERDIX 5
#define PERDIXAI 6
#define NERD2 7
#define NSTEPS 10000
#define STEP(i,n) ((NSTEPS * (i) + (n) / 2) / (n))

View File

@ -224,9 +224,11 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
break;
case 0x0606:
case 0x0A0A: // Nerd 1
case 0x0E0D: // Nerd 2
model = NERD;
break;
case 0x0E0D: // Nerd 2
model = NERD2;
break;
case 0x0404:
case 0x0909: // Petrel 1
case 0x0B0B: // Petrel 1 (newer hardware)

View File

@ -127,8 +127,8 @@ shearwater_predator_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
{
shearwater_common_device_t *device = (shearwater_common_device_t *) abstract;
// Erase the current contents of the buffer.
if (!dc_buffer_clear (buffer) || !dc_buffer_reserve (buffer, SZ_MEMORY)) {
// Pre-allocate the required amount of memory.
if (!dc_buffer_reserve (buffer, SZ_MEMORY)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}

View File

@ -71,6 +71,7 @@ struct shearwater_predator_parser_t {
unsigned int ngasmixes;
unsigned int oxygen[NGASMIXES];
unsigned int helium[NGASMIXES];
unsigned int calibrated;
double calibration[3];
unsigned int serial;
dc_divemode_t mode;
@ -159,6 +160,10 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig
parser->oxygen[i] = 0;
parser->helium[i] = 0;
}
parser->calibrated = 0;
for (unsigned int i = 0; i < 3; ++i) {
parser->calibration[i] = 0.0;
}
parser->mode = DC_DIVEMODE_OC;
*out = (dc_parser_t *) parser;
@ -182,6 +187,10 @@ shearwater_predator_parser_set_data (dc_parser_t *abstract, const unsigned char
parser->oxygen[i] = 0;
parser->helium[i] = 0;
}
parser->calibrated = 0;
for (unsigned int i = 0; i < 3; ++i) {
parser->calibration[i] = 0.0;
}
parser->mode = DC_DIVEMODE_OC;
return DC_STATUS_SUCCESS;
@ -449,17 +458,34 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
}
// Cache sensor calibration for later use
parser->calibration[0] = array_uint16_be(data + 87) / 100000.0;
parser->calibration[1] = array_uint16_be(data + 89) / 100000.0;
parser->calibration[2] = array_uint16_be(data + 91) / 100000.0;
// The Predator expects the mV output of the cells to be within 30mV
// to 70mV in 100% O2 at 1 atmosphere.
// If the calibration value is scaled with a factor 2.2, then the
// sensors lines up and matches the average.
if (parser->model == PREDATOR) {
for (size_t i = 0; i < 3; ++i) {
unsigned int nsensors = 0, ndefaults = 0;
for (size_t i = 0; i < 3; ++i) {
unsigned int calibration = array_uint16_be(data + 87 + i * 2);
parser->calibration[i] = calibration / 100000.0;
if (parser->model == PREDATOR) {
// The Predator expects the mV output of the cells to be
// within 30mV to 70mV in 100% O2 at 1 atmosphere. If the
// calibration value is scaled with a factor 2.2, then the
// sensors lines up and matches the average.
parser->calibration[i] *= 2.2;
}
if (data[86] & (1 << i)) {
if (calibration == 2100) {
ndefaults++;
}
nsensors++;
}
}
if (nsensors == ndefaults) {
// If all (calibrated) sensors still have their factory default
// calibration values (2100), they are probably not calibrated
// properly. To avoid returning incorrect ppO2 values to the
// application, they are manually disabled (e.g. marked as
// uncalibrated).
WARNING (abstract->context, "Disabled all O2 sensors due to a default calibration value.");
parser->calibrated = 0;
} else {
parser->calibrated = data[86];
}
// Cache the data for later use.
@ -630,13 +656,13 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
if (callback) callback (DC_SAMPLE_PPO2, sample, userdata);
#else
sample.ppo2 = data[offset + 12] * parser->calibration[0];
if (callback && (data[86] & 0x01)) callback (DC_SAMPLE_PPO2, sample, userdata);
if (callback && (parser->calibrated & 0x01)) callback (DC_SAMPLE_PPO2, sample, userdata);
sample.ppo2 = data[offset + 14] * parser->calibration[1];
if (callback && (data[86] & 0x02)) callback (DC_SAMPLE_PPO2, sample, userdata);
if (callback && (parser->calibrated & 0x02)) callback (DC_SAMPLE_PPO2, sample, userdata);
sample.ppo2 = data[offset + 15] * parser->calibration[2];
if (callback && (data[86] & 0x04)) callback (DC_SAMPLE_PPO2, sample, userdata);
if (callback && (parser->calibrated & 0x04)) callback (DC_SAMPLE_PPO2, sample, userdata);
#endif
}

View File

@ -149,9 +149,8 @@ suunto_eon_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
dc_status_t status = DC_STATUS_SUCCESS;
suunto_eon_device_t *device = (suunto_eon_device_t*) abstract;
// Erase the current contents of the buffer and
// pre-allocate the required amount of memory.
if (!dc_buffer_clear (buffer) || !dc_buffer_reserve (buffer, SZ_MEMORY)) {
// Pre-allocate the required amount of memory.
if (!dc_buffer_reserve (buffer, SZ_MEMORY)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}

View File

@ -94,6 +94,15 @@ static const dc_device_vtable_t suunto_eonsteel_device_vtable = {
static const char dive_directory[] = "0:/dives";
static void file_list_free (struct directory_entry *de)
{
while (de) {
struct directory_entry *next = de->next;
free (de);
de = next;
}
}
static struct directory_entry *alloc_dirent(int type, int len, const char *name)
{
struct directory_entry *res;
@ -593,7 +602,10 @@ static int read_file(suunto_eonsteel_device_t *eon, const char *filename, dc_buf
if (got > size)
got = size;
dc_buffer_append(buf, result+8, got);
if (!dc_buffer_append (buf, result + 8, got)) {
ERROR (eon->base.context, "Insufficient buffer space available.");
return -1;
}
offset += got;
size -= got;
}
@ -833,7 +845,12 @@ suunto_eonsteel_device_foreach(dc_device_t *abstract, dc_dive_callback_t callbac
return DC_STATUS_SUCCESS;
}
file = dc_buffer_new(0);
file = dc_buffer_new (16384);
if (file == NULL) {
ERROR (abstract->context, "Insufficient buffer space available.");
file_list_free (de);
return DC_STATUS_NOMEMORY;
}
progress.maximum = count_dir_entries(de);
progress.current = 0;
device_event_emit(abstract, DC_EVENT_PROGRESS, &progress);

View File

@ -143,9 +143,8 @@ suunto_solution_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
dc_status_t status = DC_STATUS_SUCCESS;
suunto_solution_device_t *device = (suunto_solution_device_t*) abstract;
// Erase the current contents of the buffer and
// allocate the required amount of memory.
if (!dc_buffer_clear (buffer) || !dc_buffer_resize (buffer, SZ_MEMORY)) {
// Allocate the required amount of memory.
if (!dc_buffer_resize (buffer, SZ_MEMORY)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}

View File

@ -454,9 +454,8 @@ suunto_vyper_read_dive (dc_device_t *abstract, dc_buffer_t *buffer, int init, dc
static dc_status_t
suunto_vyper_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
{
// Erase the current contents of the buffer and
// allocate the required amount of memory.
if (!dc_buffer_clear (buffer) || !dc_buffer_resize (buffer, SZ_MEMORY)) {
// Allocate the required amount of memory.
if (!dc_buffer_resize (buffer, SZ_MEMORY)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}

View File

@ -107,6 +107,12 @@ static const dc_iostream_vtable_t dc_usbhid_vtable = {
dc_usbhid_close, /* close */
};
static dc_mutex_t g_usbhid_mutex = DC_MUTEX_INIT;
static size_t g_usbhid_refcount = 0;
#ifdef USE_LIBUSB
static libusb_context *g_usbhid_ctx = NULL;
#endif
#if defined(USE_LIBUSB)
static dc_status_t
syserror(int errcode)
@ -129,7 +135,6 @@ syserror(int errcode)
}
}
#endif
#endif
static dc_status_t
usbhid_packet_close(dc_custom_io_t *io)
@ -206,13 +211,6 @@ dc_usbhid_custom_io (dc_context_t *context, unsigned int vid, unsigned int pid)
return DC_STATUS_SUCCESS;
}
#ifdef USBHID
static dc_mutex_t g_usbhid_mutex = DC_MUTEX_INIT;
static size_t g_usbhid_refcount = 0;
#ifdef USE_LIBUSB
static libusb_context *g_usbhid_ctx = NULL;
#endif
static void
dc_mutex_lock (dc_mutex_t *mutex)
{

View File

@ -178,9 +178,8 @@ uwatec_aladin_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
dc_status_t status = DC_STATUS_SUCCESS;
uwatec_aladin_device_t *device = (uwatec_aladin_device_t*) abstract;
// Erase the current contents of the buffer and
// pre-allocate the required amount of memory.
if (!dc_buffer_clear (buffer) || !dc_buffer_reserve (buffer, SZ_MEMORY)) {
// Pre-allocate the required amount of memory.
if (!dc_buffer_reserve (buffer, SZ_MEMORY)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}

View File

@ -450,12 +450,6 @@ uwatec_memomouse_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
uwatec_memomouse_device_t *device = (uwatec_memomouse_device_t*) abstract;
dc_status_t rc = DC_STATUS_SUCCESS;
// Erase the current contents of the buffer.
if (!dc_buffer_clear (buffer)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}
// Give the interface some time to notice the DTR
// line change from a previous transfer (if any).
dc_iostream_sleep (device->iostream, 500);

View File

@ -288,12 +288,6 @@ uwatec_meridian_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
uwatec_meridian_device_t *device = (uwatec_meridian_device_t*) abstract;
dc_status_t rc = DC_STATUS_SUCCESS;
// Erase the current contents of the buffer.
if (!dc_buffer_clear (buffer)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}
// Enable progress notifications.
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress);

View File

@ -27,9 +27,12 @@
#include "device-private.h"
#include "irda.h"
#include "array.h"
#include "platform.h"
#define ISINSTANCE(device) dc_device_isinstance((device), &uwatec_smart_device_vtable)
#define C_ARRAY_SIZE(array) (sizeof (array) / sizeof *(array))
typedef struct uwatec_smart_device_t {
dc_device_t base;
dc_iostream_t *iostream;
@ -62,22 +65,25 @@ uwatec_smart_extract_dives (dc_device_t *device, const unsigned char data[], uns
static void
uwatec_smart_discovery (unsigned int address, const char *name, unsigned int charset, unsigned int hints, void *userdata)
{
static const char *names[] = {
"Aladin Smart Com",
"Aladin Smart Pro",
"Aladin Smart Tec",
"Aladin Smart Z",
"Uwatec Aladin",
"UWATEC Galileo",
"UWATEC Galileo Sol",
};
uwatec_smart_device_t *device = (uwatec_smart_device_t*) userdata;
if (device == NULL)
if (device == NULL || name == NULL)
return;
if (strncmp (name, "UWATEC Galileo Sol", 18) == 0 ||
strncmp (name, "Uwatec Smart", 12) == 0 ||
strstr (name, "Uwatec") != NULL ||
strstr (name, "UWATEC") != NULL ||
strstr (name, "Aladin") != NULL ||
strstr (name, "ALADIN") != NULL ||
strstr (name, "Smart") != NULL ||
strstr (name, "SMART") != NULL ||
strstr (name, "Galileo") != NULL ||
strstr (name, "GALILEO") != NULL)
{
device->address = address;
for (size_t i = 0; i < C_ARRAY_SIZE(names); ++i) {
if (strcasecmp(name, names[i]) == 0) {
device->address = address;
return;
}
}
}
@ -243,12 +249,6 @@ uwatec_smart_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
uwatec_smart_device_t *device = (uwatec_smart_device_t*) abstract;
dc_status_t rc = DC_STATUS_SUCCESS;
// Erase the current contents of the buffer.
if (!dc_buffer_clear (buffer)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}
// Enable progress notifications.
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress);

View File

@ -263,9 +263,8 @@ zeagle_n2ition3_device_read (dc_device_t *abstract, unsigned int address, unsign
static dc_status_t
zeagle_n2ition3_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
{
// Erase the current contents of the buffer and
// allocate the required amount of memory.
if (!dc_buffer_clear (buffer) || !dc_buffer_resize (buffer, SZ_MEMORY)) {
// Allocate the required amount of memory.
if (!dc_buffer_resize (buffer, SZ_MEMORY)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}