From c3556d81c91958bae1729402c9f8128b9d19ddb2 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 4 Jan 2018 15:14:10 +0100 Subject: [PATCH 01/11] Use the correct model number for the Shearwater Nerd 2 Unlike the Shearwater Petrel, the Shearwater Nerd 2 appears to have a distinct model number from the Nerd. Reported-by: Janice McLaughlin --- src/descriptor.c | 2 +- src/shearwater_common.h | 1 + src/shearwater_petrel.c | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/descriptor.c b/src/descriptor.c index bdd5e60..3680683 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -292,9 +292,9 @@ static const dc_descriptor_t g_descriptors[] = { {"Shearwater", "Petrel", DC_FAMILY_SHEARWATER_PETREL, 3}, {"Shearwater", "Petrel 2", DC_FAMILY_SHEARWATER_PETREL, 3}, {"Shearwater", "Nerd", DC_FAMILY_SHEARWATER_PETREL, 4}, - {"Shearwater", "Nerd 2", DC_FAMILY_SHEARWATER_PETREL, 4}, {"Shearwater", "Perdix", DC_FAMILY_SHEARWATER_PETREL, 5}, {"Shearwater", "Perdix AI", DC_FAMILY_SHEARWATER_PETREL, 6}, + {"Shearwater", "Nerd 2", DC_FAMILY_SHEARWATER_PETREL, 7}, /* Dive Rite NiTek Q */ {"Dive Rite", "NiTek Q", DC_FAMILY_DIVERITE_NITEKQ, 0}, /* Citizen Hyper Aqualand */ diff --git a/src/shearwater_common.h b/src/shearwater_common.h index 4e3a561..3075f99 100644 --- a/src/shearwater_common.h +++ b/src/shearwater_common.h @@ -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)) diff --git a/src/shearwater_petrel.c b/src/shearwater_petrel.c index 46a7582..2f040dc 100644 --- a/src/shearwater_petrel.c +++ b/src/shearwater_petrel.c @@ -224,9 +224,11 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call model = PETREL; break; case 0x0A0A: // Nerd 1 - case 0x0E0D: // Nerd 2 model = NERD; break; + case 0x0E0D: // Nerd 2 + model = NERD2; + break; case 0x0707: model = PERDIX; break; From d23bc6e089f640eec1c09f8327a839c6586a895d Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 5 Jan 2018 18:24:50 +0100 Subject: [PATCH 02/11] Replace hardcoded size with the sizeof operator --- src/irda.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/irda.c b/src/irda.c index 972c125..b38a502 100644 --- a/src/irda.c +++ b/src/irda.c @@ -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)); From c194f559d8d8e96a3b1300ae81949a46d977b2a5 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 8 Jan 2018 23:51:21 +0100 Subject: [PATCH 03/11] Erase the buffer before calling the vtable function This guarantees that the backend will always receive an empty buffer, and eliminates the need to clear the buffer manually in every single backend. --- src/citizen_aqualand.c | 7 ------- src/cochran_commander.c | 6 ------ src/cressi_edy.c | 5 ++--- src/cressi_leonardo.c | 5 ++--- src/device.c | 5 +++++ src/diverite_nitekq.c | 4 ++-- src/hw_ostc.c | 6 ------ src/hw_ostc3.c | 6 ------ src/mares_darwin.c | 5 ++--- src/mares_iconhd.c | 5 ++--- src/mares_nemo.c | 5 ++--- src/mares_puck.c | 5 ++--- src/oceanic_common.c | 5 ++--- src/reefnet_sensus.c | 5 ++--- src/reefnet_sensuspro.c | 5 ++--- src/reefnet_sensusultra.c | 5 ++--- src/shearwater_predator.c | 4 ++-- src/suunto_eon.c | 5 ++--- src/suunto_solution.c | 5 ++--- src/suunto_vyper.c | 5 ++--- src/uwatec_aladin.c | 5 ++--- src/uwatec_g2.c | 6 ------ src/uwatec_memomouse.c | 6 ------ src/uwatec_meridian.c | 6 ------ src/uwatec_smart.c | 6 ------ src/zeagle_n2ition3.c | 5 ++--- 26 files changed, 39 insertions(+), 98 deletions(-) diff --git a/src/citizen_aqualand.c b/src/citizen_aqualand.c index 4d1817c..21894a5 100644 --- a/src/citizen_aqualand.c +++ b/src/citizen_aqualand.c @@ -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."); diff --git a/src/cochran_commander.c b/src/cochran_commander.c index e21ec7e..bbf92c7 100644 --- a/src/cochran_commander.c +++ b/src/cochran_commander.c @@ -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."); diff --git a/src/cressi_edy.c b/src/cressi_edy.c index 80e4fac..327b4aa 100644 --- a/src/cressi_edy.c +++ b/src/cressi_edy.c @@ -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; } diff --git a/src/cressi_leonardo.c b/src/cressi_leonardo.c index 4021288..e9d142b 100644 --- a/src/cressi_leonardo.c +++ b/src/cressi_leonardo.c @@ -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; } diff --git a/src/device.c b/src/device.c index aba42d5..7c3da19 100644 --- a/src/device.c +++ b/src/device.c @@ -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); } diff --git a/src/diverite_nitekq.c b/src/diverite_nitekq.c index 8524b56..6fc38b5 100644 --- a/src/diverite_nitekq.c +++ b/src/diverite_nitekq.c @@ -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; } diff --git a/src/hw_ostc.c b/src/hw_ostc.c index 8967393..941b3ef 100644 --- a/src/hw_ostc.c +++ b/src/hw_ostc.c @@ -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; diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index e240342..0391c53 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -1555,12 +1555,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; diff --git a/src/mares_darwin.c b/src/mares_darwin.c index e4d118f..0d5152d 100644 --- a/src/mares_darwin.c +++ b/src/mares_darwin.c @@ -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; } diff --git a/src/mares_iconhd.c b/src/mares_iconhd.c index bccc570..c9352e2 100644 --- a/src/mares_iconhd.c +++ b/src/mares_iconhd.c @@ -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; } diff --git a/src/mares_nemo.c b/src/mares_nemo.c index d6d4e01..a83b459 100644 --- a/src/mares_nemo.c +++ b/src/mares_nemo.c @@ -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; } diff --git a/src/mares_puck.c b/src/mares_puck.c index 5006b43..6d921f0 100644 --- a/src/mares_puck.c +++ b/src/mares_puck.c @@ -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; } diff --git a/src/oceanic_common.c b/src/oceanic_common.c index 43bc06d..1ab491d 100644 --- a/src/oceanic_common.c +++ b/src/oceanic_common.c @@ -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; } diff --git a/src/reefnet_sensus.c b/src/reefnet_sensus.c index 0fc6e52..b8d0820 100644 --- a/src/reefnet_sensus.c +++ b/src/reefnet_sensus.c @@ -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; } diff --git a/src/reefnet_sensuspro.c b/src/reefnet_sensuspro.c index 5af9181..0001f1c 100644 --- a/src/reefnet_sensuspro.c +++ b/src/reefnet_sensuspro.c @@ -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; } diff --git a/src/reefnet_sensusultra.c b/src/reefnet_sensusultra.c index a6aef5a..9ac95a2 100644 --- a/src/reefnet_sensusultra.c +++ b/src/reefnet_sensusultra.c @@ -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; } diff --git a/src/shearwater_predator.c b/src/shearwater_predator.c index a47d414..6326785 100644 --- a/src/shearwater_predator.c +++ b/src/shearwater_predator.c @@ -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; } diff --git a/src/suunto_eon.c b/src/suunto_eon.c index f41fae6..8b9138c 100644 --- a/src/suunto_eon.c +++ b/src/suunto_eon.c @@ -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; } diff --git a/src/suunto_solution.c b/src/suunto_solution.c index ffa8262..9480252 100644 --- a/src/suunto_solution.c +++ b/src/suunto_solution.c @@ -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; } diff --git a/src/suunto_vyper.c b/src/suunto_vyper.c index 89be1fc..276e633 100644 --- a/src/suunto_vyper.c +++ b/src/suunto_vyper.c @@ -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; } diff --git a/src/uwatec_aladin.c b/src/uwatec_aladin.c index dc697c2..0f1a49a 100644 --- a/src/uwatec_aladin.c +++ b/src/uwatec_aladin.c @@ -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; } diff --git a/src/uwatec_g2.c b/src/uwatec_g2.c index 5031055..fc24b71 100644 --- a/src/uwatec_g2.c +++ b/src/uwatec_g2.c @@ -275,12 +275,6 @@ uwatec_g2_device_dump (dc_device_t *abstract, dc_buffer_t *buffer) uwatec_g2_device_t *device = (uwatec_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); diff --git a/src/uwatec_memomouse.c b/src/uwatec_memomouse.c index 90466a0..ca3a747 100644 --- a/src/uwatec_memomouse.c +++ b/src/uwatec_memomouse.c @@ -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); diff --git a/src/uwatec_meridian.c b/src/uwatec_meridian.c index 5844c29..17f1b62 100644 --- a/src/uwatec_meridian.c +++ b/src/uwatec_meridian.c @@ -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); diff --git a/src/uwatec_smart.c b/src/uwatec_smart.c index d30bee6..95497c5 100644 --- a/src/uwatec_smart.c +++ b/src/uwatec_smart.c @@ -243,12 +243,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); diff --git a/src/zeagle_n2ition3.c b/src/zeagle_n2ition3.c index 01b9d5e..58f81ba 100644 --- a/src/zeagle_n2ition3.c +++ b/src/zeagle_n2ition3.c @@ -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; } From 0ae9e355f8ab3deec5c317227588a5e7a611e422 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 11 Jan 2018 22:07:56 +0100 Subject: [PATCH 04/11] Check for memory allocation errors Appending data to the buffer may fail if a memory allocation is necessary to enlarge the buffer. Hence the return value of the dc_buffer_append() call should always be checked, unless the memory was already pre-allocated or the check is deferred after the last operation. --- src/citizen_aqualand.c | 5 ++++- src/divesystem_idive.c | 13 +++++++++++-- src/hw_ostc.c | 5 ++++- src/hw_ostc3.c | 6 +++++- src/suunto_eonsteel.c | 22 ++++++++++++++++++++-- 5 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/citizen_aqualand.c b/src/citizen_aqualand.c index 21894a5..99e60e6 100644 --- a/src/citizen_aqualand.c +++ b/src/citizen_aqualand.c @@ -185,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); diff --git a/src/divesystem_idive.c b/src/divesystem_idive.c index c3d21bd..f2976b1 100644 --- a/src/divesystem_idive.c +++ b/src/divesystem_idive.c @@ -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); diff --git a/src/hw_ostc.c b/src/hw_ostc.c index 941b3ef..c47af16 100644 --- a/src/hw_ostc.c +++ b/src/hw_ostc.c @@ -587,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) { diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index 0391c53..5dec754 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -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. diff --git a/src/suunto_eonsteel.c b/src/suunto_eonsteel.c index db272d0..bac7e22 100644 --- a/src/suunto_eonsteel.c +++ b/src/suunto_eonsteel.c @@ -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; @@ -414,7 +423,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; } @@ -674,7 +686,13 @@ suunto_eonsteel_device_foreach(dc_device_t *abstract, dc_dive_callback_t callbac de = de->next; } - file = dc_buffer_new(0); + file = dc_buffer_new (16384); + if (file == NULL) { + ERROR (abstract->context, "Insufficient buffer space available."); + file_list_free (latest); + return DC_STATUS_NOMEMORY; + } + progress.maximum = count; progress.current = 0; device_event_emit(abstract, DC_EVENT_PROGRESS, &progress); From 9ca91ca5844538af148d416bd122af4c68559026 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Wed, 24 Jan 2018 08:32:42 +0100 Subject: [PATCH 05/11] Add support for the Seac Jack The Seac Jack is compatible with the DiveSystem/Ratio dive computers. --- src/descriptor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/descriptor.c b/src/descriptor.c index 3680683..49df56d 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -321,6 +321,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}, {"Cochran", "Commander I", DC_FAMILY_COCHRAN_COMMANDER, 1}, From 3e36cad5eeab3b3e96f1b522ac95928673408f0b Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 29 Jan 2018 20:47:25 +0100 Subject: [PATCH 06/11] Disable O2 sensors with default calibration values 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). --- src/shearwater_predator_parser.c | 50 ++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/src/shearwater_predator_parser.c b/src/shearwater_predator_parser.c index 8abd0f9..62ae5c6 100644 --- a/src/shearwater_predator_parser.c +++ b/src/shearwater_predator_parser.c @@ -66,6 +66,7 @@ struct shearwater_predator_parser_t { unsigned int ngasmixes; unsigned int oxygen[NGASMIXES]; unsigned int helium[NGASMIXES]; + unsigned int calibrated; double calibration[3]; dc_divemode_t mode; }; @@ -148,6 +149,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; @@ -185,6 +190,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; @@ -299,17 +308,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. @@ -462,13 +488,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 } From 9e169c9a3f67277e4e4f46f457dcb47899f1c4e5 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 30 Jan 2018 21:07:33 +0100 Subject: [PATCH 07/11] Use the correct data type for the temperature Temperatures are reported as a floating point values and not as (unsigned) integers. --- src/cochran_commander_parser.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cochran_commander_parser.c b/src/cochran_commander_parser.c index 12e8b42..e8ba76f 100644 --- a/src/cochran_commander_parser.c +++ b/src/cochran_commander_parser.c @@ -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); From 6d5ac37f99c38bac626d5ea33a3fdd1c628bf57f Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 19 Sep 2017 21:00:31 +0200 Subject: [PATCH 08/11] Use the actual IrDA device names --- src/uwatec_smart.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/uwatec_smart.c b/src/uwatec_smart.c index 95497c5..4581881 100644 --- a/src/uwatec_smart.c +++ b/src/uwatec_smart.c @@ -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; + } } } From 90eed3c790fcb1986a5ce665b8c0857bad85d486 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 5 Oct 2017 22:07:14 +0200 Subject: [PATCH 09/11] Use SDP to auto-detect the rfcomm port number When the port number is set to zero (which is an invalid value), detect the port number automatically. On Windows, we can simply supply the UUID of the serial port service, and the Windows api will take care of the discovery. On Linux (bluez), the SDP discovery needs to be performed manually to retrieve the port number. --- src/bluetooth.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 2 deletions(-) diff --git a/src/bluetooth.c b/src/bluetooth.c index b139892..1c3211e 100644 --- a/src/bluetooth.c +++ b/src/bluetooth.c @@ -30,6 +30,7 @@ #ifdef _WIN32 #ifdef HAVE_WS2BTH_H #define BLUETOOTH +#include #include #endif #else @@ -39,6 +40,8 @@ #include #include #include +#include +#include #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)); From 931d1857ce94b96c26468ce692454fcda8546875 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Wed, 25 Oct 2017 16:13:35 +0200 Subject: [PATCH 10/11] Disable some Windows specific compiler warnings The -Wno-pedantic-ms-format option is only needed for the MinGW target. But for some reason, the AX_APPEND_COMPILE_FLAGS macro enables the option for all other GCC targets too. But during compilation GCC outputs the warning "unrecognized command line option". --- configure.ac | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure.ac b/configure.ac index 9ca814b..c1e126d 100644 --- a/configure.ac +++ b/configure.ac @@ -188,6 +188,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]) From f992d201ad955340e404e076c7cd227ad5413ce3 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 5 Dec 2017 21:11:35 +0100 Subject: [PATCH 11/11] Simplify the conditional compilation Move the global variables inside an existing conditionally compiled block, to remove some of the #ifdef's. --- src/usbhid.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/usbhid.c b/src/usbhid.c index c9435c8..dab5efe 100644 --- a/src/usbhid.c +++ b/src/usbhid.c @@ -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,14 +135,6 @@ syserror(int errcode) } } #endif -#endif - -#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)