Merge tag 'v0.8.0' into Subsurface-DS9
Merge upstream version 0.8.0 into our libdc fork. Since we tracked the development branch, we already had merged all the main changes, but it's been a couple of months since the last upstream merge, and there were a few new changes upstream: - Divesoft Freedom and Liberty support - A couple of iostream abstraction layers: a new 'packet layer' and a HDLC layer, moving code from low-level dive computer downloaders to generic iostream layers. - misc minor updates * tag 'v0.8.0': (25 commits) Release version 0.8.0 Fix the date of the v0.7.0 release Add a missing filter for the Aqualung i750TC Reduce the BLE output packet size to 20 bytes again Integrate the new packet I/O in the backends Add a generic packet I/O implementation Fix a typo in the documentation Add support for the Divesoft Freedom and Liberty Integrate the HDLC stream in the eonsteel backend Add a generic HDLC I/O implementation Remove the local endianess functions Use the correct function to free resources Add the udev rules to the distribution tarball Add a README file to the contrib directory Include the revision in the Visual Studio and Android builds Don't generate the Windows version resource Move the Visual Studio project to the contrib directory Add a basic Android build system Disable the getopt argument permutation on Android Move the sign extension function to a common place ...
This commit is contained in:
commit
436063c74d
49
.github/workflows/build.yml
vendored
49
.github/workflows/build.yml
vendored
@ -122,3 +122,52 @@ jobs:
|
||||
with:
|
||||
name: ${{ github.job }}-${{ matrix.arch }}
|
||||
path: ${{ github.job }}-${{ matrix.arch }}.tar.gz
|
||||
|
||||
msvc:
|
||||
|
||||
name: Visual Studio
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [x86, x64]
|
||||
|
||||
env:
|
||||
CONFIGURATION: Release
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
install: autoconf automake libtool pkg-config make gcc
|
||||
- run: |
|
||||
autoreconf --install --force
|
||||
./configure --prefix=/usr
|
||||
make -C src revision.h
|
||||
shell: msys2 {0}
|
||||
- uses: microsoft/setup-msbuild@v1
|
||||
- run: msbuild -m -p:Platform=${{ matrix.platform }} -p:Configuration=${{ env.CONFIGURATION }} contrib/msvc/libdivecomputer.vcxproj
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ github.job }}-${{ matrix.platform }}
|
||||
path: contrib/msvc/${{ matrix.platform }}/${{ env.CONFIGURATION }}/bin
|
||||
|
||||
android:
|
||||
|
||||
name: Android
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: |
|
||||
autoreconf --install --force
|
||||
./configure --prefix=/usr
|
||||
make -C src revision.h
|
||||
- run: $ANDROID_NDK/ndk-build -C contrib/android NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ github.job }}
|
||||
path: contrib/android/libs
|
||||
|
||||
@ -16,5 +16,8 @@ pkgconfig_DATA = libdivecomputer.pc
|
||||
|
||||
EXTRA_DIST = \
|
||||
libdivecomputer.pc.in \
|
||||
msvc/libdivecomputer.vcxproj \
|
||||
msvc/libdivecomputer.vcxproj.filters
|
||||
contrib/README \
|
||||
contrib/android/Android.mk \
|
||||
contrib/msvc/libdivecomputer.vcxproj \
|
||||
contrib/msvc/libdivecomputer.vcxproj.filters \
|
||||
contrib/udev/libdivecomputer.rules
|
||||
|
||||
36
NEWS
36
NEWS
@ -1,4 +1,38 @@
|
||||
Version 0.7.0 (2020-05-07)
|
||||
Version 0.8.0 (2023-05-11)
|
||||
==========================
|
||||
|
||||
The v0.8.0 release is mainly a bugfix release, and brings in support for a
|
||||
number of new devices. This release is fully backwards compatible with the
|
||||
previous one.
|
||||
|
||||
New features:
|
||||
|
||||
* Add support for new backends:
|
||||
- excursion: Deep Six Excursion, Crest CR-4, Genesis Centauri, Tusa TC1, Scorpena Alpha
|
||||
- screen: Seac Screen and Action
|
||||
- cosmiq: Deepblu Cosmiq+
|
||||
- s1: Oceans S1
|
||||
- freedom: Divesoft Freedom and Liberty
|
||||
* Add support for some new devices:
|
||||
- Aqualung: i200C
|
||||
- Cressi: Donatello, Michelangelo, Neon
|
||||
- Mares: Puck Pro +
|
||||
- Oceanic: Geo Air
|
||||
- Ratio: iX3M 2
|
||||
- Scubapro: G2 TEK
|
||||
- Shearwater: Petrel 3, Perdix 2
|
||||
- Sherwood: Amphos Air 2.0
|
||||
* Add support for parsing the decompression model
|
||||
* Add a public api to configure the depth calibration
|
||||
* Add a public api to configure the clock synchronization
|
||||
* Add a basic Android build system
|
||||
|
||||
Removed/changed features:
|
||||
|
||||
* Migrate to Visual Studio 2013 (or newer)
|
||||
* Move the Visual Studio project to the contrib directory
|
||||
|
||||
Version 0.7.0 (2021-05-07)
|
||||
==========================
|
||||
|
||||
The main highlight of the v0.7.0 release is the introduction of the new
|
||||
|
||||
@ -253,7 +253,6 @@ AC_CONFIG_FILES([
|
||||
include/libdivecomputer/Makefile
|
||||
include/libdivecomputer/version.h
|
||||
src/Makefile
|
||||
src/libdivecomputer.rc
|
||||
doc/Makefile
|
||||
doc/doxygen.cfg
|
||||
doc/man/Makefile
|
||||
|
||||
56
contrib/README
Normal file
56
contrib/README
Normal file
@ -0,0 +1,56 @@
|
||||
Alternative build systems
|
||||
=========================
|
||||
|
||||
The autotools based build system is the official build system for the
|
||||
libdivecomputer project. But for convenience, a few alternative build systems
|
||||
are available as well. Unfortunately, these builds systems require a few extra
|
||||
steps to generate some header files.
|
||||
|
||||
If you have access to a UNIX build system (for example a Linux virtual machine,
|
||||
MinGW, Cygwin or the Windows Subsystem for Linux), you can use the autotools
|
||||
build system to generate those files:
|
||||
|
||||
$ autoreconf --install --force
|
||||
$ ./configure
|
||||
$ make -C src revision.h
|
||||
|
||||
Alternative, you can generate those files manually. First, create the version.h
|
||||
file from the version.h.in template:
|
||||
|
||||
$ cp include/libdivecomputer/version.h.in include/libdivecomputer/version.h
|
||||
|
||||
and replace all the @DC_VERSION@ placeholders with the values defined in the
|
||||
configure.ac file.
|
||||
|
||||
Next, generate the revision.h file:
|
||||
|
||||
$ echo "#define DC_VERSION_REVISION \"$(git rev-parse --verify HEAD)\"" > src/revision.h
|
||||
|
||||
The alternative build systems are ready to use now.
|
||||
|
||||
Visual Studio
|
||||
-------------
|
||||
|
||||
The Visual Studio project file can be opened in the IDE, or build directly from
|
||||
the command-line:
|
||||
|
||||
msbuild -m -p:Platform=x86|x64 -p:Configuration=Debug|Release contrib/msvc/libdivecomputer.vcxproj
|
||||
|
||||
Android NDK
|
||||
-----------
|
||||
|
||||
$ANDROID_NDK/ndk-build -C contrib/android NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk
|
||||
|
||||
Linux udev rules
|
||||
================
|
||||
|
||||
For dive computers using USB or USB HID communication, regular users typically
|
||||
don't have the necessary permissions to access the device nodes. This can be
|
||||
fixed with some udev rules.
|
||||
|
||||
Install the udev rules, and reload them:
|
||||
|
||||
$ sudo cp contrib/udev/libdivecomputer.rules /etc/udev/rules.d/
|
||||
$ sudo udevadm control --reload
|
||||
|
||||
Note: the provided udev rules assume the user is in the plugdev group.
|
||||
143
contrib/android/Android.mk
Normal file
143
contrib/android/Android.mk
Normal file
@ -0,0 +1,143 @@
|
||||
LOCAL_PATH := $(call my-dir)/../..
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := libdivecomputer
|
||||
LOCAL_CFLAGS := -DENABLE_LOGGING -DHAVE_VERSION_SUFFIX -DHAVE_PTHREAD_H -DHAVE_STRERROR_R -DHAVE_CLOCK_GETTIME -DHAVE_LOCALTIME_R -DHAVE_GMTIME_R -DHAVE_TIMEGM -DHAVE_STRUCT_TM_TM_GMTOFF
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
|
||||
LOCAL_SRC_FILES := \
|
||||
src/aes.c \
|
||||
src/array.c \
|
||||
src/atomics_cobalt.c \
|
||||
src/atomics_cobalt_parser.c \
|
||||
src/bluetooth.c \
|
||||
src/buffer.c \
|
||||
src/checksum.c \
|
||||
src/citizen_aqualand.c \
|
||||
src/citizen_aqualand_parser.c \
|
||||
src/cochran_commander.c \
|
||||
src/cochran_commander_parser.c \
|
||||
src/common.c \
|
||||
src/context.c \
|
||||
src/cressi_edy.c \
|
||||
src/cressi_edy_parser.c \
|
||||
src/cressi_goa.c \
|
||||
src/cressi_goa_parser.c \
|
||||
src/cressi_leonardo.c \
|
||||
src/cressi_leonardo_parser.c \
|
||||
src/custom.c \
|
||||
src/datetime.c \
|
||||
src/deepblu_cosmiq.c \
|
||||
src/deepblu_cosmiq_parser.c \
|
||||
src/deepsix_excursion.c \
|
||||
src/deepsix_excursion_parser.c \
|
||||
src/descriptor.c \
|
||||
src/device.c \
|
||||
src/diverite_nitekq.c \
|
||||
src/diverite_nitekq_parser.c \
|
||||
src/divesoft_freedom.c \
|
||||
src/divesoft_freedom_parser.c \
|
||||
src/divesystem_idive.c \
|
||||
src/divesystem_idive_parser.c \
|
||||
src/hdlc.c \
|
||||
src/hw_frog.c \
|
||||
src/hw_ostc3.c \
|
||||
src/hw_ostc.c \
|
||||
src/hw_ostc_parser.c \
|
||||
src/ihex.c \
|
||||
src/iostream.c \
|
||||
src/irda.c \
|
||||
src/iterator.c \
|
||||
src/liquivision_lynx.c \
|
||||
src/liquivision_lynx_parser.c \
|
||||
src/mares_common.c \
|
||||
src/mares_darwin.c \
|
||||
src/mares_darwin_parser.c \
|
||||
src/mares_iconhd.c \
|
||||
src/mares_iconhd_parser.c \
|
||||
src/mares_nemo.c \
|
||||
src/mares_nemo_parser.c \
|
||||
src/mares_puck.c \
|
||||
src/mclean_extreme.c \
|
||||
src/mclean_extreme_parser.c \
|
||||
src/oceanic_atom2.c \
|
||||
src/oceanic_atom2_parser.c \
|
||||
src/oceanic_common.c \
|
||||
src/oceanic_veo250.c \
|
||||
src/oceanic_veo250_parser.c \
|
||||
src/oceanic_vtpro.c \
|
||||
src/oceanic_vtpro_parser.c \
|
||||
src/oceans_s1.c \
|
||||
src/oceans_s1_common.c \
|
||||
src/oceans_s1_parser.c \
|
||||
src/packet.c \
|
||||
src/parser.c \
|
||||
src/platform.c \
|
||||
src/rbstream.c \
|
||||
src/reefnet_sensus.c \
|
||||
src/reefnet_sensus_parser.c \
|
||||
src/reefnet_sensuspro.c \
|
||||
src/reefnet_sensuspro_parser.c \
|
||||
src/reefnet_sensusultra.c \
|
||||
src/reefnet_sensusultra_parser.c \
|
||||
src/ringbuffer.c \
|
||||
src/seac_screen.c \
|
||||
src/seac_screen_parser.c \
|
||||
src/serial_posix.c \
|
||||
src/shearwater_common.c \
|
||||
src/shearwater_petrel.c \
|
||||
src/shearwater_predator.c \
|
||||
src/shearwater_predator_parser.c \
|
||||
src/socket.c \
|
||||
src/sporasub_sp2.c \
|
||||
src/sporasub_sp2_parser.c \
|
||||
src/suunto_common2.c \
|
||||
src/suunto_common.c \
|
||||
src/suunto_d9.c \
|
||||
src/suunto_d9_parser.c \
|
||||
src/suunto_eon.c \
|
||||
src/suunto_eon_parser.c \
|
||||
src/suunto_eonsteel.c \
|
||||
src/suunto_eonsteel_parser.c \
|
||||
src/suunto_solution.c \
|
||||
src/suunto_solution_parser.c \
|
||||
src/suunto_vyper2.c \
|
||||
src/suunto_vyper.c \
|
||||
src/suunto_vyper_parser.c \
|
||||
src/tecdiving_divecomputereu.c \
|
||||
src/tecdiving_divecomputereu_parser.c \
|
||||
src/timer.c \
|
||||
src/usb.c \
|
||||
src/usbhid.c \
|
||||
src/uwatec_aladin.c \
|
||||
src/uwatec_memomouse.c \
|
||||
src/uwatec_memomouse_parser.c \
|
||||
src/uwatec_smart.c \
|
||||
src/uwatec_smart_parser.c \
|
||||
src/version.c \
|
||||
src/zeagle_n2ition3.c
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := dctool
|
||||
LOCAL_SHARED_LIBRARIES := libdivecomputer
|
||||
LOCAL_CFLAGS := -DHAVE_UNISTD_H -DHAVE_GETOPT_H -DHAVE_GETOPT_LONG -DHAVE_DECL_OPTRESET=1
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
|
||||
LOCAL_SRC_FILES := \
|
||||
examples/common.c \
|
||||
examples/dctool.c \
|
||||
examples/dctool_download.c \
|
||||
examples/dctool_dump.c \
|
||||
examples/dctool_fwupdate.c \
|
||||
examples/dctool_help.c \
|
||||
examples/dctool_list.c \
|
||||
examples/dctool_parse.c \
|
||||
examples/dctool_read.c \
|
||||
examples/dctool_scan.c \
|
||||
examples/dctool_timesync.c \
|
||||
examples/dctool_version.c \
|
||||
examples/dctool_write.c \
|
||||
examples/output.c \
|
||||
examples/output_raw.c \
|
||||
examples/output_xml.c \
|
||||
examples/utils.c
|
||||
include $(BUILD_EXECUTABLE)
|
||||
407
contrib/msvc/libdivecomputer.vcxproj
Normal file
407
contrib/msvc/libdivecomputer.vcxproj
Normal file
@ -0,0 +1,407 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{CEA7215A-D6B5-4840-8086-3C854F371997}</ProjectGuid>
|
||||
<RootNamespace>libdivecomputer</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)$(PlatformTarget)\$(Configuration)\bin\</OutDir>
|
||||
<IntDir>$(PlatformTarget)\$(Configuration)\obj\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)$(PlatformTarget)\$(Configuration)\bin\</OutDir>
|
||||
<IntDir>$(PlatformTarget)\$(Configuration)\obj\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)$(PlatformTarget)\$(Configuration)\bin\</OutDir>
|
||||
<IntDir>$(PlatformTarget)\$(Configuration)\obj\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)$(PlatformTarget)\$(Configuration)\bin\</OutDir>
|
||||
<IntDir>$(PlatformTarget)\$(Configuration)\obj\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBDIVECOMPUTER_EXPORTS;ENABLE_LOGGING;HAVE_VERSION_SUFFIX;HAVE_AF_IRDA_H;HAVE_WS2BTH_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>$(OutDir)libdivecomputer.def</ModuleDefinitionFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBDIVECOMPUTER_EXPORTS;ENABLE_LOGGING;HAVE_VERSION_SUFFIX;HAVE_AF_IRDA_H;HAVE_WS2BTH_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>$(OutDir)libdivecomputer.def</ModuleDefinitionFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBDIVECOMPUTER_EXPORTS;ENABLE_LOGGING;HAVE_VERSION_SUFFIX;HAVE_AF_IRDA_H;HAVE_WS2BTH_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>$(OutDir)libdivecomputer.def</ModuleDefinitionFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBDIVECOMPUTER_EXPORTS;ENABLE_LOGGING;HAVE_VERSION_SUFFIX;HAVE_AF_IRDA_H;HAVE_WS2BTH_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>$(OutDir)libdivecomputer.def</ModuleDefinitionFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\aes.c" />
|
||||
<ClCompile Include="..\..\src\array.c" />
|
||||
<ClCompile Include="..\..\src\atomics_cobalt.c" />
|
||||
<ClCompile Include="..\..\src\atomics_cobalt_parser.c" />
|
||||
<ClCompile Include="..\..\src\bluetooth.c" />
|
||||
<ClCompile Include="..\..\src\buffer.c" />
|
||||
<ClCompile Include="..\..\src\checksum.c" />
|
||||
<ClCompile Include="..\..\src\citizen_aqualand.c" />
|
||||
<ClCompile Include="..\..\src\citizen_aqualand_parser.c" />
|
||||
<ClCompile Include="..\..\src\cochran_commander.c" />
|
||||
<ClCompile Include="..\..\src\cochran_commander_parser.c" />
|
||||
<ClCompile Include="..\..\src\common.c" />
|
||||
<ClCompile Include="..\..\src\context.c" />
|
||||
<ClCompile Include="..\..\src\cressi_edy.c" />
|
||||
<ClCompile Include="..\..\src\cressi_edy_parser.c" />
|
||||
<ClCompile Include="..\..\src\cressi_goa.c" />
|
||||
<ClCompile Include="..\..\src\cressi_goa_parser.c" />
|
||||
<ClCompile Include="..\..\src\cressi_leonardo.c" />
|
||||
<ClCompile Include="..\..\src\cressi_leonardo_parser.c" />
|
||||
<ClCompile Include="..\..\src\custom.c" />
|
||||
<ClCompile Include="..\..\src\datetime.c" />
|
||||
<ClCompile Include="..\..\src\deepblu_cosmiq.c" />
|
||||
<ClCompile Include="..\..\src\deepblu_cosmiq_parser.c" />
|
||||
<ClCompile Include="..\..\src\deepsix_excursion.c" />
|
||||
<ClCompile Include="..\..\src\deepsix_excursion_parser.c" />
|
||||
<ClCompile Include="..\..\src\descriptor.c" />
|
||||
<ClCompile Include="..\..\src\device.c" />
|
||||
<ClCompile Include="..\..\src\diverite_nitekq.c" />
|
||||
<ClCompile Include="..\..\src\diverite_nitekq_parser.c" />
|
||||
<ClCompile Include="..\..\src\divesoft_freedom.c" />
|
||||
<ClCompile Include="..\..\src\divesoft_freedom_parser.c" />
|
||||
<ClCompile Include="..\..\src\divesystem_idive.c" />
|
||||
<ClCompile Include="..\..\src\divesystem_idive_parser.c" />
|
||||
<ClCompile Include="..\..\src\hdlc.c" />
|
||||
<ClCompile Include="..\..\src\hw_frog.c" />
|
||||
<ClCompile Include="..\..\src\hw_ostc.c" />
|
||||
<ClCompile Include="..\..\src\hw_ostc3.c" />
|
||||
<ClCompile Include="..\..\src\hw_ostc_parser.c" />
|
||||
<ClCompile Include="..\..\src\ihex.c" />
|
||||
<ClCompile Include="..\..\src\iostream.c" />
|
||||
<ClCompile Include="..\..\src\irda.c" />
|
||||
<ClCompile Include="..\..\src\iterator.c" />
|
||||
<ClCompile Include="..\..\src\liquivision_lynx.c" />
|
||||
<ClCompile Include="..\..\src\liquivision_lynx_parser.c" />
|
||||
<ClCompile Include="..\..\src\mares_common.c" />
|
||||
<ClCompile Include="..\..\src\mares_darwin.c" />
|
||||
<ClCompile Include="..\..\src\mares_darwin_parser.c" />
|
||||
<ClCompile Include="..\..\src\mares_iconhd.c" />
|
||||
<ClCompile Include="..\..\src\mares_iconhd_parser.c" />
|
||||
<ClCompile Include="..\..\src\mares_nemo.c" />
|
||||
<ClCompile Include="..\..\src\mares_nemo_parser.c" />
|
||||
<ClCompile Include="..\..\src\mares_puck.c" />
|
||||
<ClCompile Include="..\..\src\mclean_extreme.c" />
|
||||
<ClCompile Include="..\..\src\mclean_extreme_parser.c" />
|
||||
<ClCompile Include="..\..\src\oceanic_atom2.c" />
|
||||
<ClCompile Include="..\..\src\oceanic_atom2_parser.c" />
|
||||
<ClCompile Include="..\..\src\oceanic_common.c" />
|
||||
<ClCompile Include="..\..\src\oceanic_veo250.c" />
|
||||
<ClCompile Include="..\..\src\oceanic_veo250_parser.c" />
|
||||
<ClCompile Include="..\..\src\oceanic_vtpro.c" />
|
||||
<ClCompile Include="..\..\src\oceanic_vtpro_parser.c" />
|
||||
<ClCompile Include="..\..\src\oceans_s1.c" />
|
||||
<ClCompile Include="..\..\src\oceans_s1_common.c" />
|
||||
<ClCompile Include="..\..\src\oceans_s1_parser.c" />
|
||||
<ClCompile Include="..\..\src\packet.c" />
|
||||
<ClCompile Include="..\..\src\parser.c" />
|
||||
<ClCompile Include="..\..\src\platform.c" />
|
||||
<ClCompile Include="..\..\src\rbstream.c" />
|
||||
<ClCompile Include="..\..\src\reefnet_sensus.c" />
|
||||
<ClCompile Include="..\..\src\reefnet_sensuspro.c" />
|
||||
<ClCompile Include="..\..\src\reefnet_sensuspro_parser.c" />
|
||||
<ClCompile Include="..\..\src\reefnet_sensusultra.c" />
|
||||
<ClCompile Include="..\..\src\reefnet_sensusultra_parser.c" />
|
||||
<ClCompile Include="..\..\src\reefnet_sensus_parser.c" />
|
||||
<ClCompile Include="..\..\src\ringbuffer.c" />
|
||||
<ClCompile Include="..\..\src\seac_screen.c" />
|
||||
<ClCompile Include="..\..\src\seac_screen_parser.c" />
|
||||
<ClCompile Include="..\..\src\serial_win32.c" />
|
||||
<ClCompile Include="..\..\src\shearwater_common.c" />
|
||||
<ClCompile Include="..\..\src\shearwater_petrel.c" />
|
||||
<ClCompile Include="..\..\src\shearwater_predator.c" />
|
||||
<ClCompile Include="..\..\src\shearwater_predator_parser.c" />
|
||||
<ClCompile Include="..\..\src\socket.c" />
|
||||
<ClCompile Include="..\..\src\sporasub_sp2.c" />
|
||||
<ClCompile Include="..\..\src\sporasub_sp2_parser.c" />
|
||||
<ClCompile Include="..\..\src\suunto_common.c" />
|
||||
<ClCompile Include="..\..\src\suunto_common2.c" />
|
||||
<ClCompile Include="..\..\src\suunto_d9.c" />
|
||||
<ClCompile Include="..\..\src\suunto_d9_parser.c" />
|
||||
<ClCompile Include="..\..\src\suunto_eon.c" />
|
||||
<ClCompile Include="..\..\src\suunto_eonsteel.c" />
|
||||
<ClCompile Include="..\..\src\suunto_eonsteel_parser.c" />
|
||||
<ClCompile Include="..\..\src\suunto_eon_parser.c" />
|
||||
<ClCompile Include="..\..\src\suunto_solution.c" />
|
||||
<ClCompile Include="..\..\src\suunto_solution_parser.c" />
|
||||
<ClCompile Include="..\..\src\suunto_vyper.c" />
|
||||
<ClCompile Include="..\..\src\suunto_vyper2.c" />
|
||||
<ClCompile Include="..\..\src\suunto_vyper_parser.c" />
|
||||
<ClCompile Include="..\..\src\tecdiving_divecomputereu.c" />
|
||||
<ClCompile Include="..\..\src\tecdiving_divecomputereu_parser.c" />
|
||||
<ClCompile Include="..\..\src\timer.c" />
|
||||
<ClCompile Include="..\..\src\usb.c" />
|
||||
<ClCompile Include="..\..\src\usbhid.c" />
|
||||
<ClCompile Include="..\..\src\uwatec_aladin.c" />
|
||||
<ClCompile Include="..\..\src\uwatec_memomouse.c" />
|
||||
<ClCompile Include="..\..\src\uwatec_memomouse_parser.c" />
|
||||
<ClCompile Include="..\..\src\uwatec_smart.c" />
|
||||
<ClCompile Include="..\..\src\uwatec_smart_parser.c" />
|
||||
<ClCompile Include="..\..\src\version.c" />
|
||||
<ClCompile Include="..\..\src\zeagle_n2ition3.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\include\libdivecomputer\atomics_cobalt.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\ble.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\bluetooth.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\buffer.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\common.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\context.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\custom.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\datetime.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\descriptor.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\device.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\divesystem_idive.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\hw_frog.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\hw_ostc.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\hw_ostc3.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\ioctl.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\iostream.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\irda.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\iterator.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\oceanic_atom2.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\oceanic_veo250.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\oceanic_vtpro.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\parser.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\reefnet_sensus.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\reefnet_sensuspro.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\reefnet_sensusultra.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\serial.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\suunto_d9.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\suunto_eon.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\suunto_vyper2.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\units.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\usb.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\usbhid.h" />
|
||||
<ClInclude Include="..\..\include\libdivecomputer\version.h" />
|
||||
<ClInclude Include="..\..\src\aes.h" />
|
||||
<ClInclude Include="..\..\src\array.h" />
|
||||
<ClInclude Include="..\..\src\atomics_cobalt.h" />
|
||||
<ClInclude Include="..\..\src\checksum.h" />
|
||||
<ClInclude Include="..\..\src\citizen_aqualand.h" />
|
||||
<ClInclude Include="..\..\src\cochran_commander.h" />
|
||||
<ClInclude Include="..\..\src\common-private.h" />
|
||||
<ClInclude Include="..\..\src\context-private.h" />
|
||||
<ClInclude Include="..\..\src\cressi_edy.h" />
|
||||
<ClInclude Include="..\..\src\cressi_goa.h" />
|
||||
<ClInclude Include="..\..\src\cressi_leonardo.h" />
|
||||
<ClInclude Include="..\..\src\deepblu_cosmiq.h" />
|
||||
<ClInclude Include="..\..\src\deepsix_excursion.h" />
|
||||
<ClInclude Include="..\..\src\descriptor-private.h" />
|
||||
<ClInclude Include="..\..\src\device-private.h" />
|
||||
<ClInclude Include="..\..\src\diverite_nitekq.h" />
|
||||
<ClInclude Include="..\..\src\divesoft_freedom.h" />
|
||||
<ClInclude Include="..\..\src\divesystem_idive.h" />
|
||||
<ClInclude Include="..\..\src\hdlc.h" />
|
||||
<ClInclude Include="..\..\src\hw_frog.h" />
|
||||
<ClInclude Include="..\..\src\hw_ostc.h" />
|
||||
<ClInclude Include="..\..\src\hw_ostc3.h" />
|
||||
<ClInclude Include="..\..\src\ihex.h" />
|
||||
<ClInclude Include="..\..\src\iostream-private.h" />
|
||||
<ClInclude Include="..\..\src\iterator-private.h" />
|
||||
<ClInclude Include="..\..\src\liquivision_lynx.h" />
|
||||
<ClInclude Include="..\..\src\mares_common.h" />
|
||||
<ClInclude Include="..\..\src\mares_darwin.h" />
|
||||
<ClInclude Include="..\..\src\mares_iconhd.h" />
|
||||
<ClInclude Include="..\..\src\mares_nemo.h" />
|
||||
<ClInclude Include="..\..\src\mares_puck.h" />
|
||||
<ClInclude Include="..\..\src\mclean_extreme.h" />
|
||||
<ClInclude Include="..\..\src\oceanic_atom2.h" />
|
||||
<ClInclude Include="..\..\src\oceanic_common.h" />
|
||||
<ClInclude Include="..\..\src\oceanic_veo250.h" />
|
||||
<ClInclude Include="..\..\src\oceanic_vtpro.h" />
|
||||
<ClInclude Include="..\..\src\oceans_s1.h" />
|
||||
<ClInclude Include="..\..\src\oceans_s1_common.h" />
|
||||
<ClInclude Include="..\..\src\packet.h" />
|
||||
<ClInclude Include="..\..\src\parser-private.h" />
|
||||
<ClInclude Include="..\..\src\platform.h" />
|
||||
<ClInclude Include="..\..\src\rbstream.h" />
|
||||
<ClInclude Include="..\..\src\reefnet_sensus.h" />
|
||||
<ClInclude Include="..\..\src\reefnet_sensuspro.h" />
|
||||
<ClInclude Include="..\..\src\reefnet_sensusultra.h" />
|
||||
<ClInclude Include="..\..\src\revision.h" />
|
||||
<ClInclude Include="..\..\src\ringbuffer.h" />
|
||||
<ClInclude Include="..\..\src\seac_screen.h" />
|
||||
<ClInclude Include="..\..\src\shearwater_common.h" />
|
||||
<ClInclude Include="..\..\src\shearwater_petrel.h" />
|
||||
<ClInclude Include="..\..\src\shearwater_predator.h" />
|
||||
<ClInclude Include="..\..\src\socket.h" />
|
||||
<ClInclude Include="..\..\src\sporasub_sp2.h" />
|
||||
<ClInclude Include="..\..\src\suunto_common.h" />
|
||||
<ClInclude Include="..\..\src\suunto_common2.h" />
|
||||
<ClInclude Include="..\..\src\suunto_d9.h" />
|
||||
<ClInclude Include="..\..\src\suunto_eon.h" />
|
||||
<ClInclude Include="..\..\src\suunto_eonsteel.h" />
|
||||
<ClInclude Include="..\..\src\suunto_solution.h" />
|
||||
<ClInclude Include="..\..\src\suunto_vyper.h" />
|
||||
<ClInclude Include="..\..\src\suunto_vyper2.h" />
|
||||
<ClInclude Include="..\..\src\tecdiving_divecomputereu.h" />
|
||||
<ClInclude Include="..\..\src\timer.h" />
|
||||
<ClInclude Include="..\..\src\uwatec_aladin.h" />
|
||||
<ClInclude Include="..\..\src\uwatec_memomouse.h" />
|
||||
<ClInclude Include="..\..\src\uwatec_smart.h" />
|
||||
<ClInclude Include="..\..\src\zeagle_n2ition3.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\..\src\libdivecomputer.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="..\..\src\libdivecomputer.symbols">
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">echo EXPORTS > "$(OutDir)libdivecomputer.def" && type "%(FullPath)" >> "$(OutDir)libdivecomputer.def"</Command>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">echo EXPORTS > "$(OutDir)libdivecomputer.def" && type "%(FullPath)" >> "$(OutDir)libdivecomputer.def"</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)libdivecomputer.def;%(Outputs)</Outputs>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)libdivecomputer.def;%(Outputs)</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo EXPORTS > "$(OutDir)libdivecomputer.def" && type "%(FullPath)" >> "$(OutDir)libdivecomputer.def"</Command>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">echo EXPORTS > "$(OutDir)libdivecomputer.def" && type "%(FullPath)" >> "$(OutDir)libdivecomputer.def"</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)libdivecomputer.def;%(Outputs)</Outputs>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)libdivecomputer.def;%(Outputs)</Outputs>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@ -82,7 +82,7 @@ is
|
||||
.Sh SEE ALSO
|
||||
.Xr dc_datetime_localtime 3 ,
|
||||
.Xr dc_datetime_mktime 3 ,
|
||||
.Xr dc_datetime_new 3
|
||||
.Xr dc_datetime_now 3
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Lb libdivecomputer
|
||||
|
||||
@ -82,7 +82,7 @@ is
|
||||
.Sh SEE ALSO
|
||||
.Xr dc_datetime_gmtime 3 ,
|
||||
.Xr dc_datetime_mktime 3 ,
|
||||
.Xr dc_datetime_new 3
|
||||
.Xr dc_datetime_now 3
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Lb libdivecomputer
|
||||
|
||||
@ -47,7 +47,7 @@ may not sanely be converted.
|
||||
.Sh SEE ALSO
|
||||
.Xr dc_datetime_gmtime 3 ,
|
||||
.Xr dc_datetime_localtime 3 ,
|
||||
.Xr dc_datetime_new 3
|
||||
.Xr dc_datetime_now 3
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Lb libdivecomputer
|
||||
|
||||
@ -98,6 +98,7 @@ static const backend_table_t g_backends[] = {
|
||||
{"screen", DC_FAMILY_SEAC_SCREEN, 0},
|
||||
{"cosmiq", DC_FAMILY_DEEPBLU_COSMIQ, 0},
|
||||
{"s1", DC_FAMILY_OCEANS_S1, 0},
|
||||
{"freedom", DC_FAMILY_DIVESOFT_FREEDOM, 19},
|
||||
|
||||
// Not merged upstream yet
|
||||
{"descentmk1", DC_FAMILY_GARMIN, 0},
|
||||
|
||||
@ -50,7 +50,7 @@
|
||||
#define RESET 1
|
||||
#endif
|
||||
|
||||
#if defined(__GLIBC__) || defined(__MINGW32__) || defined(BSD)
|
||||
#if defined(__GLIBC__) || defined(__MINGW32__) || defined(BSD) || defined(__ANDROID__)
|
||||
#define NOPERMUTATION "+"
|
||||
#else
|
||||
#define NOPERMUTATION ""
|
||||
|
||||
@ -122,6 +122,8 @@ typedef enum dc_family_t {
|
||||
DC_FAMILY_DEEPBLU_COSMIQ = (21 << 16),
|
||||
/* Oceans S1 */
|
||||
DC_FAMILY_OCEANS_S1 = (22 << 16),
|
||||
/* Divesoft Freedom */
|
||||
DC_FAMILY_DIVESOFT_FREEDOM = (23 << 16),
|
||||
|
||||
// Not merged upstream yet
|
||||
/* Garmin */
|
||||
|
||||
@ -1,388 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{CEA7215A-D6B5-4840-8086-3C854F371997}</ProjectGuid>
|
||||
<RootNamespace>libdivecomputer</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)$(PlatformTarget)\$(Configuration)\bin\</OutDir>
|
||||
<IntDir>$(PlatformTarget)\$(Configuration)\obj\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)$(PlatformTarget)\$(Configuration)\bin\</OutDir>
|
||||
<IntDir>$(PlatformTarget)\$(Configuration)\obj\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)$(PlatformTarget)\$(Configuration)\bin\</OutDir>
|
||||
<IntDir>$(PlatformTarget)\$(Configuration)\obj\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)$(PlatformTarget)\$(Configuration)\bin\</OutDir>
|
||||
<IntDir>$(PlatformTarget)\$(Configuration)\obj\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBDIVECOMPUTER_EXPORTS;ENABLE_LOGGING;HAVE_AF_IRDA_H;HAVE_WS2BTH_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>$(OutDir)libdivecomputer.def</ModuleDefinitionFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBDIVECOMPUTER_EXPORTS;ENABLE_LOGGING;HAVE_AF_IRDA_H;HAVE_WS2BTH_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>$(OutDir)libdivecomputer.def</ModuleDefinitionFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBDIVECOMPUTER_EXPORTS;ENABLE_LOGGING;HAVE_AF_IRDA_H;HAVE_WS2BTH_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>$(OutDir)libdivecomputer.def</ModuleDefinitionFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBDIVECOMPUTER_EXPORTS;ENABLE_LOGGING;HAVE_AF_IRDA_H;HAVE_WS2BTH_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>$(OutDir)libdivecomputer.def</ModuleDefinitionFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\src\aes.c" />
|
||||
<ClCompile Include="..\src\array.c" />
|
||||
<ClCompile Include="..\src\atomics_cobalt.c" />
|
||||
<ClCompile Include="..\src\atomics_cobalt_parser.c" />
|
||||
<ClCompile Include="..\src\bluetooth.c" />
|
||||
<ClCompile Include="..\src\buffer.c" />
|
||||
<ClCompile Include="..\src\checksum.c" />
|
||||
<ClCompile Include="..\src\citizen_aqualand.c" />
|
||||
<ClCompile Include="..\src\citizen_aqualand_parser.c" />
|
||||
<ClCompile Include="..\src\cochran_commander.c" />
|
||||
<ClCompile Include="..\src\cochran_commander_parser.c" />
|
||||
<ClCompile Include="..\src\common.c" />
|
||||
<ClCompile Include="..\src\context.c" />
|
||||
<ClCompile Include="..\src\cressi_edy.c" />
|
||||
<ClCompile Include="..\src\cressi_edy_parser.c" />
|
||||
<ClCompile Include="..\src\cressi_goa.c" />
|
||||
<ClCompile Include="..\src\cressi_goa_parser.c" />
|
||||
<ClCompile Include="..\src\cressi_leonardo.c" />
|
||||
<ClCompile Include="..\src\cressi_leonardo_parser.c" />
|
||||
<ClCompile Include="..\src\custom.c" />
|
||||
<ClCompile Include="..\src\datetime.c" />
|
||||
<ClCompile Include="..\src\deepblu_cosmiq.c" />
|
||||
<ClCompile Include="..\src\deepblu_cosmiq_parser.c" />
|
||||
<ClCompile Include="..\src\deepsix_excursion.c" />
|
||||
<ClCompile Include="..\src\deepsix_excursion_parser.c" />
|
||||
<ClCompile Include="..\src\descriptor.c" />
|
||||
<ClCompile Include="..\src\device.c" />
|
||||
<ClCompile Include="..\src\diverite_nitekq.c" />
|
||||
<ClCompile Include="..\src\diverite_nitekq_parser.c" />
|
||||
<ClCompile Include="..\src\divesystem_idive.c" />
|
||||
<ClCompile Include="..\src\divesystem_idive_parser.c" />
|
||||
<ClCompile Include="..\src\hw_frog.c" />
|
||||
<ClCompile Include="..\src\hw_ostc.c" />
|
||||
<ClCompile Include="..\src\hw_ostc3.c" />
|
||||
<ClCompile Include="..\src\hw_ostc_parser.c" />
|
||||
<ClCompile Include="..\src\ihex.c" />
|
||||
<ClCompile Include="..\src\iostream.c" />
|
||||
<ClCompile Include="..\src\irda.c" />
|
||||
<ClCompile Include="..\src\iterator.c" />
|
||||
<ClCompile Include="..\src\liquivision_lynx.c" />
|
||||
<ClCompile Include="..\src\liquivision_lynx_parser.c" />
|
||||
<ClCompile Include="..\src\mares_common.c" />
|
||||
<ClCompile Include="..\src\mares_darwin.c" />
|
||||
<ClCompile Include="..\src\mares_darwin_parser.c" />
|
||||
<ClCompile Include="..\src\mares_iconhd.c" />
|
||||
<ClCompile Include="..\src\mares_iconhd_parser.c" />
|
||||
<ClCompile Include="..\src\mares_nemo.c" />
|
||||
<ClCompile Include="..\src\mares_nemo_parser.c" />
|
||||
<ClCompile Include="..\src\mares_puck.c" />
|
||||
<ClCompile Include="..\src\mclean_extreme.c" />
|
||||
<ClCompile Include="..\src\mclean_extreme_parser.c" />
|
||||
<ClCompile Include="..\src\oceanic_atom2.c" />
|
||||
<ClCompile Include="..\src\oceanic_atom2_parser.c" />
|
||||
<ClCompile Include="..\src\oceanic_common.c" />
|
||||
<ClCompile Include="..\src\oceanic_veo250.c" />
|
||||
<ClCompile Include="..\src\oceanic_veo250_parser.c" />
|
||||
<ClCompile Include="..\src\oceanic_vtpro.c" />
|
||||
<ClCompile Include="..\src\oceanic_vtpro_parser.c" />
|
||||
<ClCompile Include="..\src\oceans_s1.c" />
|
||||
<ClCompile Include="..\src\oceans_s1_common.c" />
|
||||
<ClCompile Include="..\src\oceans_s1_parser.c" />
|
||||
<ClCompile Include="..\src\parser.c" />
|
||||
<ClCompile Include="..\src\platform.c" />
|
||||
<ClCompile Include="..\src\rbstream.c" />
|
||||
<ClCompile Include="..\src\reefnet_sensus.c" />
|
||||
<ClCompile Include="..\src\reefnet_sensuspro.c" />
|
||||
<ClCompile Include="..\src\reefnet_sensuspro_parser.c" />
|
||||
<ClCompile Include="..\src\reefnet_sensusultra.c" />
|
||||
<ClCompile Include="..\src\reefnet_sensusultra_parser.c" />
|
||||
<ClCompile Include="..\src\reefnet_sensus_parser.c" />
|
||||
<ClCompile Include="..\src\ringbuffer.c" />
|
||||
<ClCompile Include="..\src\seac_screen.c" />
|
||||
<ClCompile Include="..\src\seac_screen_parser.c" />
|
||||
<ClCompile Include="..\src\serial_win32.c" />
|
||||
<ClCompile Include="..\src\shearwater_common.c" />
|
||||
<ClCompile Include="..\src\shearwater_petrel.c" />
|
||||
<ClCompile Include="..\src\shearwater_predator.c" />
|
||||
<ClCompile Include="..\src\shearwater_predator_parser.c" />
|
||||
<ClCompile Include="..\src\socket.c" />
|
||||
<ClCompile Include="..\src\sporasub_sp2.c" />
|
||||
<ClCompile Include="..\src\sporasub_sp2_parser.c" />
|
||||
<ClCompile Include="..\src\suunto_common.c" />
|
||||
<ClCompile Include="..\src\suunto_common2.c" />
|
||||
<ClCompile Include="..\src\suunto_d9.c" />
|
||||
<ClCompile Include="..\src\suunto_d9_parser.c" />
|
||||
<ClCompile Include="..\src\suunto_eon.c" />
|
||||
<ClCompile Include="..\src\suunto_eonsteel.c" />
|
||||
<ClCompile Include="..\src\suunto_eonsteel_parser.c" />
|
||||
<ClCompile Include="..\src\suunto_eon_parser.c" />
|
||||
<ClCompile Include="..\src\suunto_solution.c" />
|
||||
<ClCompile Include="..\src\suunto_solution_parser.c" />
|
||||
<ClCompile Include="..\src\suunto_vyper.c" />
|
||||
<ClCompile Include="..\src\suunto_vyper2.c" />
|
||||
<ClCompile Include="..\src\suunto_vyper_parser.c" />
|
||||
<ClCompile Include="..\src\tecdiving_divecomputereu.c" />
|
||||
<ClCompile Include="..\src\tecdiving_divecomputereu_parser.c" />
|
||||
<ClCompile Include="..\src\timer.c" />
|
||||
<ClCompile Include="..\src\usb.c" />
|
||||
<ClCompile Include="..\src\usbhid.c" />
|
||||
<ClCompile Include="..\src\uwatec_aladin.c" />
|
||||
<ClCompile Include="..\src\uwatec_memomouse.c" />
|
||||
<ClCompile Include="..\src\uwatec_memomouse_parser.c" />
|
||||
<ClCompile Include="..\src\uwatec_smart.c" />
|
||||
<ClCompile Include="..\src\uwatec_smart_parser.c" />
|
||||
<ClCompile Include="..\src\version.c" />
|
||||
<ClCompile Include="..\src\zeagle_n2ition3.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\include\libdivecomputer\atomics_cobalt.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\ble.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\bluetooth.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\buffer.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\common.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\context.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\custom.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\datetime.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\descriptor.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\device.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\divesystem_idive.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\hw_frog.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\hw_ostc.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\hw_ostc3.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\ioctl.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\iostream.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\irda.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\iterator.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\oceanic_atom2.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\oceanic_veo250.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\oceanic_vtpro.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\parser.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\reefnet_sensus.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\reefnet_sensuspro.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\reefnet_sensusultra.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\serial.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\suunto_d9.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\suunto_eon.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\suunto_vyper2.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\units.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\usb.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\usbhid.h" />
|
||||
<ClInclude Include="..\include\libdivecomputer\version.h" />
|
||||
<ClInclude Include="..\src\aes.h" />
|
||||
<ClInclude Include="..\src\array.h" />
|
||||
<ClInclude Include="..\src\atomics_cobalt.h" />
|
||||
<ClInclude Include="..\src\checksum.h" />
|
||||
<ClInclude Include="..\src\citizen_aqualand.h" />
|
||||
<ClInclude Include="..\src\cochran_commander.h" />
|
||||
<ClInclude Include="..\src\common-private.h" />
|
||||
<ClInclude Include="..\src\context-private.h" />
|
||||
<ClInclude Include="..\src\cressi_edy.h" />
|
||||
<ClInclude Include="..\src\cressi_goa.h" />
|
||||
<ClInclude Include="..\src\cressi_leonardo.h" />
|
||||
<ClInclude Include="..\src\deepblu_cosmiq.h" />
|
||||
<ClInclude Include="..\src\deepsix_excursion.h" />
|
||||
<ClInclude Include="..\src\descriptor-private.h" />
|
||||
<ClInclude Include="..\src\device-private.h" />
|
||||
<ClInclude Include="..\src\diverite_nitekq.h" />
|
||||
<ClInclude Include="..\src\divesystem_idive.h" />
|
||||
<ClInclude Include="..\src\hw_frog.h" />
|
||||
<ClInclude Include="..\src\hw_ostc.h" />
|
||||
<ClInclude Include="..\src\hw_ostc3.h" />
|
||||
<ClInclude Include="..\src\ihex.h" />
|
||||
<ClInclude Include="..\src\iostream-private.h" />
|
||||
<ClInclude Include="..\src\iterator-private.h" />
|
||||
<ClInclude Include="..\src\liquivision_lynx.h" />
|
||||
<ClInclude Include="..\src\mares_common.h" />
|
||||
<ClInclude Include="..\src\mares_darwin.h" />
|
||||
<ClInclude Include="..\src\mares_iconhd.h" />
|
||||
<ClInclude Include="..\src\mares_nemo.h" />
|
||||
<ClInclude Include="..\src\mares_puck.h" />
|
||||
<ClInclude Include="..\src\mclean_extreme.h" />
|
||||
<ClInclude Include="..\src\oceanic_atom2.h" />
|
||||
<ClInclude Include="..\src\oceanic_common.h" />
|
||||
<ClInclude Include="..\src\oceanic_veo250.h" />
|
||||
<ClInclude Include="..\src\oceanic_vtpro.h" />
|
||||
<ClInclude Include="..\src\oceans_s1.h" />
|
||||
<ClInclude Include="..\src\oceans_s1_common.h" />
|
||||
<ClInclude Include="..\src\parser-private.h" />
|
||||
<ClInclude Include="..\src\platform.h" />
|
||||
<ClInclude Include="..\src\rbstream.h" />
|
||||
<ClInclude Include="..\src\reefnet_sensus.h" />
|
||||
<ClInclude Include="..\src\reefnet_sensuspro.h" />
|
||||
<ClInclude Include="..\src\reefnet_sensusultra.h" />
|
||||
<ClInclude Include="..\src\revision.h" />
|
||||
<ClInclude Include="..\src\ringbuffer.h" />
|
||||
<ClInclude Include="..\src\seac_screen.h" />
|
||||
<ClInclude Include="..\src\shearwater_common.h" />
|
||||
<ClInclude Include="..\src\shearwater_petrel.h" />
|
||||
<ClInclude Include="..\src\shearwater_predator.h" />
|
||||
<ClInclude Include="..\src\socket.h" />
|
||||
<ClInclude Include="..\src\sporasub_sp2.h" />
|
||||
<ClInclude Include="..\src\suunto_common.h" />
|
||||
<ClInclude Include="..\src\suunto_common2.h" />
|
||||
<ClInclude Include="..\src\suunto_d9.h" />
|
||||
<ClInclude Include="..\src\suunto_eon.h" />
|
||||
<ClInclude Include="..\src\suunto_eonsteel.h" />
|
||||
<ClInclude Include="..\src\suunto_solution.h" />
|
||||
<ClInclude Include="..\src\suunto_vyper.h" />
|
||||
<ClInclude Include="..\src\suunto_vyper2.h" />
|
||||
<ClInclude Include="..\src\tecdiving_divecomputereu.h" />
|
||||
<ClInclude Include="..\src\timer.h" />
|
||||
<ClInclude Include="..\src\uwatec_aladin.h" />
|
||||
<ClInclude Include="..\src\uwatec_memomouse.h" />
|
||||
<ClInclude Include="..\src\uwatec_smart.h" />
|
||||
<ClInclude Include="..\src\zeagle_n2ition3.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\src\libdivecomputer.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="..\src\libdivecomputer.symbols">
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">echo EXPORTS > "$(OutDir)libdivecomputer.def" && type "%(FullPath)" >> "$(OutDir)libdivecomputer.def"</Command>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">echo EXPORTS > "$(OutDir)libdivecomputer.def" && type "%(FullPath)" >> "$(OutDir)libdivecomputer.def"</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)libdivecomputer.def;%(Outputs)</Outputs>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)libdivecomputer.def;%(Outputs)</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo EXPORTS > "$(OutDir)libdivecomputer.def" && type "%(FullPath)" >> "$(OutDir)libdivecomputer.def"</Command>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">echo EXPORTS > "$(OutDir)libdivecomputer.def" && type "%(FullPath)" >> "$(OutDir)libdivecomputer.def"</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)libdivecomputer.def;%(Outputs)</Outputs>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)libdivecomputer.def;%(Outputs)</Outputs>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@ -80,6 +80,9 @@ libdivecomputer_la_SOURCES = \
|
||||
deepblu_cosmiq.h deepblu_cosmiq.c deepblu_cosmiq_parser.c \
|
||||
oceans_s1_common.h oceans_s1_common.c \
|
||||
oceans_s1.h oceans_s1.c oceans_s1_parser.c \
|
||||
divesoft_freedom.h divesoft_freedom.c divesoft_freedom_parser.c \
|
||||
hdlc.h hdlc.c \
|
||||
packet.h packet.c \
|
||||
socket.h socket.c \
|
||||
irda.c \
|
||||
usb.c \
|
||||
@ -109,7 +112,7 @@ libdivecomputer.exp: libdivecomputer.symbols
|
||||
$(AM_V_GEN) sed -e '/^$$/d' $< > $@
|
||||
|
||||
.rc.lo:
|
||||
$(AM_V_GEN) $(LIBTOOL) --silent --tag=CC --mode=compile $(RC) $(DEFS) $(DEFAULT_INCLUDES) $< -o $@
|
||||
$(AM_V_GEN) $(LIBTOOL) --silent --tag=CC --mode=compile $(RC) $(DEFS) $(DEFAULT_INCLUDES) $(AM_CPPFLAGS) $< -o $@
|
||||
|
||||
libdivecomputer.lo: revision.h
|
||||
|
||||
|
||||
20
src/array.c
20
src/array.c
@ -384,3 +384,23 @@ dec2bcd (unsigned char value)
|
||||
unsigned char lo = value % 10;
|
||||
return (hi << 4) | lo;
|
||||
}
|
||||
|
||||
/*
|
||||
* When turning a two's-complement number with a certain number
|
||||
* of bits into one with more bits, the sign bit must be repeated
|
||||
* in all the extra bits.
|
||||
*/
|
||||
unsigned int
|
||||
signextend (unsigned int value, unsigned int nbits)
|
||||
{
|
||||
if (nbits <= 0 || nbits > 32)
|
||||
return 0;
|
||||
|
||||
unsigned int signbit = 1U << (nbits - 1);
|
||||
unsigned int mask = signbit - 1;
|
||||
|
||||
if ((value & signbit) == signbit)
|
||||
return value | ~mask;
|
||||
else
|
||||
return value & mask;
|
||||
}
|
||||
|
||||
@ -123,6 +123,9 @@ bcd2dec (unsigned char value);
|
||||
unsigned char
|
||||
dec2bcd (unsigned char value);
|
||||
|
||||
unsigned int
|
||||
signextend (unsigned int value, unsigned int nbits);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
180
src/checksum.c
180
src/checksum.c
@ -68,8 +68,13 @@ checksum_xor_uint8 (const unsigned char data[], unsigned int size, unsigned char
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Polynomial: 0x1021
|
||||
* RefIn: False
|
||||
* RefOut: False
|
||||
*/
|
||||
unsigned short
|
||||
checksum_crc16_ccitt (const unsigned char data[], unsigned int size, unsigned short init)
|
||||
checksum_crc16_ccitt (const unsigned char data[], unsigned int size, unsigned short init, unsigned short xorout)
|
||||
{
|
||||
static const unsigned short crc_ccitt_table[] = {
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
|
||||
@ -110,11 +115,170 @@ checksum_crc16_ccitt (const unsigned char data[], unsigned int size, unsigned sh
|
||||
for (unsigned int i = 0; i < size; ++i)
|
||||
crc = (crc << 8) ^ crc_ccitt_table[(crc >> 8) ^ data[i]];
|
||||
|
||||
return crc;
|
||||
return crc ^ xorout;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Polynomial: 0x1021
|
||||
* RefIn: True
|
||||
* RefOut: True
|
||||
*/
|
||||
unsigned short
|
||||
checksum_crc16r_ccitt (const unsigned char data[], unsigned int size, unsigned short init, unsigned short xorout)
|
||||
{
|
||||
static const unsigned short crc_ccitt_table[] = {
|
||||
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
|
||||
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
|
||||
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
|
||||
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
|
||||
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
|
||||
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
|
||||
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
|
||||
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
|
||||
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
|
||||
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
|
||||
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
|
||||
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
|
||||
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
|
||||
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
|
||||
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
|
||||
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
|
||||
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
|
||||
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
|
||||
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
|
||||
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
|
||||
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
|
||||
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
|
||||
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
|
||||
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
|
||||
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
|
||||
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
|
||||
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
|
||||
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
|
||||
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
|
||||
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
|
||||
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
|
||||
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
|
||||
};
|
||||
|
||||
unsigned short crc = init;
|
||||
for (unsigned int i = 0; i < size; ++i)
|
||||
crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ data[i]) & 0xff];
|
||||
|
||||
return crc ^ xorout;
|
||||
}
|
||||
|
||||
/*
|
||||
* Polynomial: 0x8005
|
||||
* RefIn: False
|
||||
* RefOut: False
|
||||
*/
|
||||
unsigned short
|
||||
checksum_crc16_ansi (const unsigned char data[], unsigned int size, unsigned short init, unsigned short xorout)
|
||||
{
|
||||
static const unsigned short crc_ccitt_table[] = {
|
||||
0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011,
|
||||
0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
|
||||
0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,
|
||||
0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041,
|
||||
0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2,
|
||||
0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,
|
||||
0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1,
|
||||
0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082,
|
||||
0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,
|
||||
0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1,
|
||||
0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1,
|
||||
0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,
|
||||
0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151,
|
||||
0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162,
|
||||
0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,
|
||||
0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101,
|
||||
0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312,
|
||||
0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,
|
||||
0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371,
|
||||
0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342,
|
||||
0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,
|
||||
0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2,
|
||||
0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2,
|
||||
0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,
|
||||
0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291,
|
||||
0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2,
|
||||
0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,
|
||||
0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1,
|
||||
0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252,
|
||||
0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,
|
||||
0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231,
|
||||
0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202
|
||||
};
|
||||
|
||||
unsigned short crc = init;
|
||||
for (unsigned int i = 0; i < size; ++i)
|
||||
crc = (crc << 8) ^ crc_ccitt_table[(crc >> 8) ^ data[i]];
|
||||
|
||||
return crc ^ xorout;
|
||||
}
|
||||
|
||||
/*
|
||||
* Polynomial: 0x8005
|
||||
* RefIn: True
|
||||
* RefOut: True
|
||||
*/
|
||||
unsigned short
|
||||
checksum_crc16r_ansi (const unsigned char data[], unsigned int size, unsigned short init, unsigned short xorout)
|
||||
{
|
||||
static const unsigned short crc_ccitt_table[] = {
|
||||
0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
|
||||
0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
|
||||
0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
|
||||
0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
|
||||
0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
|
||||
0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
|
||||
0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
|
||||
0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
|
||||
0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
|
||||
0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
|
||||
0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
|
||||
0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
|
||||
0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
|
||||
0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
|
||||
0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
|
||||
0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
|
||||
0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
|
||||
0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
|
||||
0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
|
||||
0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
|
||||
0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
|
||||
0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
|
||||
0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
|
||||
0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
|
||||
0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
|
||||
0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
|
||||
0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
|
||||
0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
|
||||
0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
|
||||
0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
|
||||
0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
|
||||
0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
|
||||
};
|
||||
|
||||
unsigned short crc = init;
|
||||
for (unsigned int i = 0; i < size; ++i)
|
||||
crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ data[i]) & 0xff];
|
||||
|
||||
return crc ^ xorout;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Polynomial: 0x04C11DB7
|
||||
* Init: 0xffffffff
|
||||
* XorOut: 0xffffffff
|
||||
* RefIn: True
|
||||
* RefOut: True
|
||||
*/
|
||||
unsigned int
|
||||
checksum_crc32 (const unsigned char data[], unsigned int size)
|
||||
checksum_crc32r (const unsigned char data[], unsigned int size)
|
||||
{
|
||||
static const unsigned int crc_table[] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
@ -158,8 +322,16 @@ checksum_crc32 (const unsigned char data[], unsigned int size)
|
||||
return crc ^ 0xffffffff;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Polynomial: 0x04C11DB7
|
||||
* Init: 0xffffffff
|
||||
* XorOut: 0xffffffff
|
||||
* RefIn: False
|
||||
* RefOut: False
|
||||
*/
|
||||
unsigned int
|
||||
checksum_crc32b (const unsigned char data[], unsigned int size)
|
||||
checksum_crc32 (const unsigned char data[], unsigned int size)
|
||||
{
|
||||
static const unsigned int crc_table[] = {
|
||||
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
|
||||
|
||||
@ -39,14 +39,23 @@ unsigned char
|
||||
checksum_xor_uint8 (const unsigned char data[], unsigned int size, unsigned char init);
|
||||
|
||||
unsigned short
|
||||
checksum_crc16_ccitt (const unsigned char data[], unsigned int size, unsigned short init);
|
||||
checksum_crc16_ccitt (const unsigned char data[], unsigned int size, unsigned short init, unsigned short xorout);
|
||||
|
||||
unsigned short
|
||||
checksum_crc16r_ccitt (const unsigned char data[], unsigned int size, unsigned short init, unsigned short xorout);
|
||||
|
||||
unsigned short
|
||||
checksum_crc16_ansi (const unsigned char data[], unsigned int size, unsigned short init, unsigned short xorout);
|
||||
|
||||
unsigned short
|
||||
checksum_crc16r_ansi (const unsigned char data[], unsigned int size, unsigned short init, unsigned short xorout);
|
||||
|
||||
unsigned int
|
||||
checksum_crc32r (const unsigned char data[], unsigned int size);
|
||||
|
||||
unsigned int
|
||||
checksum_crc32 (const unsigned char data[], unsigned int size);
|
||||
|
||||
unsigned int
|
||||
checksum_crc32b (const unsigned char data[], unsigned int size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
@ -93,7 +93,7 @@ cressi_goa_device_send (cressi_goa_device_t *device, unsigned char cmd, const un
|
||||
if (size) {
|
||||
memcpy (packet + 5, data, size);
|
||||
}
|
||||
crc = checksum_crc16_ccitt (packet + 3, size + 2, 0x000);
|
||||
crc = checksum_crc16_ccitt (packet + 3, size + 2, 0x000, 0x0000);
|
||||
packet[5 + size + 0] = (crc ) & 0xFF; // Low
|
||||
packet[5 + size + 1] = (crc >> 8) & 0xFF; // High
|
||||
packet[5 + size + 2] = TRAILER;
|
||||
@ -155,7 +155,7 @@ cressi_goa_device_receive (cressi_goa_device_t *device, unsigned char data[], un
|
||||
|
||||
// Verify the checksum of the packet.
|
||||
unsigned short crc = array_uint16_le (packet + length + 5);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (packet + 3, length + 2, 0x0000);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (packet + 3, length + 2, 0x0000, 0x0000);
|
||||
if (crc != ccrc) {
|
||||
ERROR (abstract->context, "Unexpected answer checksum.");
|
||||
return DC_STATUS_PROTOCOL;
|
||||
@ -203,7 +203,7 @@ cressi_goa_device_download (cressi_goa_device_t *device, dc_buffer_t *buffer, dc
|
||||
|
||||
// Verify the checksum of the packet.
|
||||
unsigned short crc = array_uint16_le (packet + sizeof(packet) - 2);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (packet + 3, sizeof(packet) - 5, 0x0000);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (packet + 3, sizeof(packet) - 5, 0x0000, 0x0000);
|
||||
if (crc != ccrc) {
|
||||
ERROR (abstract->context, "Unexpected answer checksum.");
|
||||
return DC_STATUS_PROTOCOL;
|
||||
|
||||
@ -84,7 +84,7 @@ cressi_leonardo_make_ascii (const unsigned char raw[], unsigned int rsize, unsig
|
||||
array_convert_bin2hex (raw, rsize, ascii + 1, 2 * rsize);
|
||||
|
||||
// Checksum
|
||||
unsigned short crc = checksum_crc16_ccitt (ascii + 1, 2 * rsize, 0xffff);
|
||||
unsigned short crc = checksum_crc16_ccitt (ascii + 1, 2 * rsize, 0xffff, 0x0000);
|
||||
unsigned char checksum[] = {
|
||||
(crc >> 8) & 0xFF, // High
|
||||
(crc ) & 0xFF}; // Low
|
||||
@ -129,7 +129,7 @@ cressi_leonardo_packet (cressi_leonardo_device_t *device, const unsigned char co
|
||||
|
||||
// Verify the checksum of the packet.
|
||||
unsigned short crc = array_uint16_be (checksum);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (answer + 1, asize - 6, 0xffff);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (answer + 1, asize - 6, 0xffff, 0x0000);
|
||||
if (crc != ccrc) {
|
||||
ERROR (abstract->context, "Unexpected answer checksum.");
|
||||
return DC_STATUS_PROTOCOL;
|
||||
@ -372,7 +372,7 @@ cressi_leonardo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
|
||||
// Verify the checksum.
|
||||
unsigned int csum1 = array_uint16_be (checksum);
|
||||
unsigned int csum2 = checksum_crc16_ccitt (data, SZ_MEMORY, 0xffff);
|
||||
unsigned int csum2 = checksum_crc16_ccitt (data, SZ_MEMORY, 0xffff, 0x0000);
|
||||
if (csum1 != csum2) {
|
||||
ERROR (abstract->context, "Unexpected answer bytes.");
|
||||
return DC_STATUS_PROTOCOL;
|
||||
|
||||
@ -65,6 +65,7 @@ static int dc_filter_atomic (dc_transport_t transport, const void *userdata, voi
|
||||
static int dc_filter_deepsix (dc_transport_t transport, const void *userdata, void *params);
|
||||
static int dc_filter_deepblu (dc_transport_t transport, const void *userdata, void *params);
|
||||
static int dc_filter_oceans (dc_transport_t transport, const void *userdata, void *params);
|
||||
static int dc_filter_divesoft (dc_transport_t transport, const void *userdata, void *params);
|
||||
|
||||
// Not merged upstream yet
|
||||
static int dc_filter_garmin (dc_transport_t transport, const void *userdata, void *params);
|
||||
@ -454,6 +455,9 @@ static const dc_descriptor_t g_descriptors[] = {
|
||||
{"Deepblu", "Cosmiq+", DC_FAMILY_DEEPBLU_COSMIQ, 0, DC_TRANSPORT_BLE, dc_filter_deepblu},
|
||||
/* Oceans S1 */
|
||||
{"Oceans", "S1", DC_FAMILY_OCEANS_S1, 0, DC_TRANSPORT_BLE, dc_filter_oceans},
|
||||
/* Divesoft Freedom */
|
||||
{"Divesoft", "Freedom", DC_FAMILY_DIVESOFT_FREEDOM, 19, DC_TRANSPORT_BLE, dc_filter_divesoft},
|
||||
{"Divesoft", "Liberty", DC_FAMILY_DIVESOFT_FREEDOM, 10, DC_TRANSPORT_BLE, dc_filter_divesoft},
|
||||
|
||||
// Not merged upstream yet
|
||||
/* Garmin -- model numbers as defined in FIT format; USB product id is (0x4000 | model) */
|
||||
@ -808,6 +812,20 @@ static int dc_filter_oceans (dc_transport_t transport, const void *userdata, voi
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dc_filter_divesoft (dc_transport_t transport, const void *userdata, void *params)
|
||||
{
|
||||
static const char * const bluetooth[] = {
|
||||
"Freedom",
|
||||
"Liberty",
|
||||
};
|
||||
|
||||
if (transport == DC_TRANSPORT_BLE) {
|
||||
return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_prefix);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Not merged upstream yet
|
||||
static int dc_filter_garmin (dc_transport_t transport, const void *userdata, void *params)
|
||||
{
|
||||
|
||||
@ -64,6 +64,7 @@
|
||||
#include "seac_screen.h"
|
||||
#include "deepblu_cosmiq.h"
|
||||
#include "oceans_s1.h"
|
||||
#include "divesoft_freedom.h"
|
||||
|
||||
// Not merged upstream yet
|
||||
#include "garmin.h"
|
||||
@ -242,6 +243,9 @@ dc_device_open (dc_device_t **out, dc_context_t *context, dc_descriptor_t *descr
|
||||
case DC_FAMILY_OCEANS_S1:
|
||||
rc = oceans_s1_device_open (&device, context, iostream);
|
||||
break;
|
||||
case DC_FAMILY_DIVESOFT_FREEDOM:
|
||||
rc = divesoft_freedom_device_open (&device, context, iostream);
|
||||
break;
|
||||
default:
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
|
||||
595
src/divesoft_freedom.c
Normal file
595
src/divesoft_freedom.c
Normal file
@ -0,0 +1,595 @@
|
||||
/*
|
||||
* libdivecomputer
|
||||
*
|
||||
* Copyright (C) 2023 Jan Matoušek, Jef Driesen
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "divesoft_freedom.h"
|
||||
#include "context-private.h"
|
||||
#include "device-private.h"
|
||||
#include "platform.h"
|
||||
#include "checksum.h"
|
||||
#include "array.h"
|
||||
#include "hdlc.h"
|
||||
|
||||
#define MAXDATA 256
|
||||
|
||||
#define HEADER_SIGNATURE_V1 0x45766944 // "DivE"
|
||||
#define HEADER_SIGNATURE_V2 0x45566944 // "DiVE"
|
||||
|
||||
#define HEADER_SIZE_V1 32
|
||||
#define HEADER_SIZE_V2 64
|
||||
|
||||
#define RECORD_SIZE 16
|
||||
#define FINGERPRINT_SIZE 20
|
||||
|
||||
#define INVALID 0xFFFFFFFF
|
||||
#define COMPRESSION 1
|
||||
#define DIRECTION 1
|
||||
#define NRECORDS 100
|
||||
|
||||
#define DEVICE_CCR_CU 1 // Liberty HW rev. 1.X
|
||||
#define DEVICE_FREEDOM 2 // Freedom HW rev. 2.X
|
||||
#define DEVICE_FREEDOM3 5 // Freedom HW rev. 3.X
|
||||
#define DEVICE_CCR_CU15 10 // Liberty HW rev. 2.X, Bluetooth enabled
|
||||
#define DEVICE_FREEDOM4 19 // Freedom HW rev. 4.X, Bluetooth enabled
|
||||
|
||||
typedef enum message_t {
|
||||
MSG_ECHO = 0,
|
||||
MSG_RESULT = 1,
|
||||
MSG_CONNECT = 2,
|
||||
MSG_CONNECTED = 3,
|
||||
MSG_VERSION = 4,
|
||||
MSG_VERSION_RSP = 5,
|
||||
MSG_DIVE_DATA = 64,
|
||||
MSG_DIVE_DATA_RSP = 65,
|
||||
MSG_DIVE_LIST = 66,
|
||||
MSG_DIVE_LIST_V1 = 67,
|
||||
MSG_DIVE_LIST_V2 = 71,
|
||||
} message_t;
|
||||
|
||||
typedef struct divesoft_freedom_device_t {
|
||||
dc_device_t base;
|
||||
dc_iostream_t *iostream;
|
||||
unsigned char fingerprint[FINGERPRINT_SIZE];
|
||||
unsigned int seqnum;
|
||||
} divesoft_freedom_device_t;
|
||||
|
||||
static dc_status_t divesoft_freedom_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
|
||||
static dc_status_t divesoft_freedom_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata);
|
||||
static dc_status_t divesoft_freedom_device_close (dc_device_t *device);
|
||||
|
||||
static const dc_device_vtable_t divesoft_freedom_device_vtable = {
|
||||
sizeof(divesoft_freedom_device_t),
|
||||
DC_FAMILY_DIVESOFT_FREEDOM,
|
||||
divesoft_freedom_device_set_fingerprint, /* set_fingerprint */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
NULL, /* dump */
|
||||
divesoft_freedom_device_foreach, /* foreach */
|
||||
NULL, /* timesync */
|
||||
divesoft_freedom_device_close, /* close */
|
||||
};
|
||||
|
||||
static dc_status_t
|
||||
divesoft_freedom_send (divesoft_freedom_device_t *device, message_t message, const unsigned char data[], size_t size)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
size_t nbytes = 0, count = 0;
|
||||
while (1) {
|
||||
size_t len = size - nbytes;
|
||||
if (len > MAXDATA)
|
||||
len = MAXDATA;
|
||||
|
||||
unsigned int islast = nbytes + len == size;
|
||||
|
||||
unsigned char packet[6 + MAXDATA + 2] = {0};
|
||||
packet[0] = ((count & 0x0F) << 4) | (device->seqnum & 0x0F);
|
||||
packet[1] = 0x80 | (islast << 6);
|
||||
array_uint16_le_set (packet + 2, message);
|
||||
array_uint16_le_set (packet + 4, len);
|
||||
if (len) {
|
||||
memcpy (packet + 6, data + nbytes, len);
|
||||
}
|
||||
unsigned short crc = checksum_crc16r_ccitt (packet, len + 6, 0xFFFF, 0xFFFF);
|
||||
array_uint16_le_set (packet + 6 + len, crc);
|
||||
|
||||
HEXDUMP (abstract->context, DC_LOGLEVEL_DEBUG, "cmd", packet, 6 + len + 2);
|
||||
|
||||
status = dc_iostream_write (device->iostream, packet, 6 + len + 2, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the packet.");
|
||||
return status;
|
||||
}
|
||||
|
||||
nbytes += len;
|
||||
count++;
|
||||
|
||||
if (islast)
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
divesoft_freedom_recv (divesoft_freedom_device_t *device, dc_event_progress_t *progress, message_t *message, dc_buffer_t *buffer)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
unsigned int msg = INVALID;
|
||||
|
||||
unsigned int count = 0;
|
||||
while (1) {
|
||||
size_t len = 0;
|
||||
unsigned char packet[6 + MAXDATA + 2] = {0};
|
||||
status = dc_iostream_read (device->iostream, packet, sizeof(packet), &len);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the packet.");
|
||||
return status;
|
||||
}
|
||||
|
||||
HEXDUMP (abstract->context, DC_LOGLEVEL_DEBUG, "rcv", packet, len);
|
||||
|
||||
if (len < 8) {
|
||||
ERROR (abstract->context, "Unexpected packet length (" DC_PRINTF_SIZE ").", len);
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
|
||||
unsigned int seqnum = packet[0];
|
||||
unsigned int flags = packet[1];
|
||||
unsigned int type = array_uint16_le (packet + 2);
|
||||
unsigned int length = array_uint16_le (packet + 4);
|
||||
|
||||
unsigned int expected = ((count & 0x0F) << 4) | (device->seqnum & 0x0F);
|
||||
if (seqnum != expected) {
|
||||
ERROR (abstract->context, "Unexpected packet sequence number (%u %u).", seqnum, expected);
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
|
||||
if ((flags & ~0x40) != 0) {
|
||||
ERROR (abstract->context, "Unexpected packet flags (%u).", flags);
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
|
||||
if (length != len - 8) {
|
||||
ERROR (abstract->context, "Unexpected packet length (%u " DC_PRINTF_SIZE ").", length, len - 8);
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
|
||||
if (msg == INVALID) {
|
||||
msg = type;
|
||||
} else if (msg != type) {
|
||||
ERROR (abstract->context, "Unexpected packet type (%u).", msg);
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
|
||||
unsigned short crc = array_uint16_le (packet + len - 2);
|
||||
unsigned short ccrc = checksum_crc16r_ccitt (packet, len - 2, 0xFFFF, 0xFFFF);
|
||||
if (crc != ccrc) {
|
||||
ERROR (abstract->context, "Unexpected packet checksum (%04x %04x).", crc, ccrc);
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
|
||||
// Update and emit a progress event.
|
||||
if (progress) {
|
||||
progress->current += len - 8;
|
||||
// Limit the progress to the maximum size. This could happen if the
|
||||
// dive computer sends more data than requested for some reason.
|
||||
if (progress->current > progress->maximum) {
|
||||
WARNING (abstract->context, "Progress exceeds the maximum size.");
|
||||
progress->current = progress->maximum;
|
||||
}
|
||||
device_event_emit (abstract, DC_EVENT_PROGRESS, progress);
|
||||
}
|
||||
|
||||
if (!dc_buffer_append (buffer, packet + 6, len - 8)) {
|
||||
ERROR (abstract->context, "Insufficient buffer space available.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
if (flags & 0x40)
|
||||
break;
|
||||
}
|
||||
|
||||
if (message)
|
||||
*message = msg;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
divesoft_freedom_transfer (divesoft_freedom_device_t *device, dc_event_progress_t *progress, message_t cmd, const unsigned char data[], size_t size, message_t *msg, dc_buffer_t *buffer)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
device->seqnum++;
|
||||
|
||||
status = divesoft_freedom_send (device, cmd, data, size);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return status;
|
||||
}
|
||||
|
||||
status = divesoft_freedom_recv (device, progress, msg, buffer);
|
||||
if(status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive response.");
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
divesoft_freedom_download (divesoft_freedom_device_t *device, message_t cmd, const unsigned char cdata[], size_t csize, unsigned char rdata[], size_t rsize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
dc_buffer_t *buffer = dc_buffer_new (rsize);
|
||||
if (buffer == NULL) {
|
||||
ERROR (abstract->context, "Failed to allocate memory.");
|
||||
status = DC_STATUS_NOMEMORY;
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
message_t msg = MSG_ECHO;
|
||||
status = divesoft_freedom_transfer (device, NULL, cmd, cdata, csize, &msg, buffer);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to transfer the packet.");
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
if (msg != cmd + 1) {
|
||||
ERROR (abstract->context, "Unexpected response message (%u).", msg);
|
||||
status = DC_STATUS_PROTOCOL;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
size_t length = dc_buffer_get_size (buffer);
|
||||
if (length != rsize) {
|
||||
ERROR (abstract->context, "Unexpected response length (" DC_PRINTF_SIZE " " DC_PRINTF_SIZE ").", length, rsize);
|
||||
status = DC_STATUS_PROTOCOL;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
if (rsize) {
|
||||
memcpy (rdata, dc_buffer_get_data (buffer), rsize);
|
||||
}
|
||||
|
||||
error_free:
|
||||
dc_buffer_free (buffer);
|
||||
error_exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
divesoft_freedom_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t *iostream)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
divesoft_freedom_device_t *device = NULL;
|
||||
|
||||
if (out == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
device = (divesoft_freedom_device_t *) dc_device_allocate (context, &divesoft_freedom_device_vtable);
|
||||
if (device == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
// Set the default values.
|
||||
device->iostream = NULL;
|
||||
memset(device->fingerprint, 0, sizeof(device->fingerprint));
|
||||
device->seqnum = 0;
|
||||
|
||||
// Setup the HDLC communication.
|
||||
status = dc_hdlc_open (&device->iostream, context, iostream, 244, 244);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to create the HDLC stream.");
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (115200 8N1).
|
||||
status = dc_iostream_configure (device->iostream, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
goto error_free_hdlc;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (3000ms).
|
||||
status = dc_iostream_set_timeout (device->iostream, 3000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
goto error_free_hdlc;
|
||||
}
|
||||
|
||||
// Initiate the connection with the dive computer.
|
||||
const char client[] = "libdivecomputer";
|
||||
unsigned char cmd_connect[2 + sizeof(client) - 1] = {0};
|
||||
array_uint16_le_set (cmd_connect, COMPRESSION);
|
||||
memcpy (cmd_connect + 2, client, sizeof(client) - 1);
|
||||
unsigned char rsp_connect[36] = {0};
|
||||
status = divesoft_freedom_download (device, MSG_CONNECT, cmd_connect, sizeof(cmd_connect), rsp_connect, sizeof(rsp_connect));
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to connect to the device.");
|
||||
goto error_free_hdlc;
|
||||
}
|
||||
|
||||
DEBUG (context, "Connection: compression=%u, protocol=%u.%u, serial=%.16s",
|
||||
array_uint16_le (rsp_connect),
|
||||
rsp_connect[2], rsp_connect[3],
|
||||
rsp_connect + 4);
|
||||
|
||||
*out = (dc_device_t *) device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_free_hdlc:
|
||||
dc_iostream_close (device->iostream);
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
divesoft_freedom_device_close (dc_device_t *abstract)
|
||||
{
|
||||
divesoft_freedom_device_t *device = (divesoft_freedom_device_t *) abstract;
|
||||
|
||||
return dc_iostream_close (device->iostream);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
divesoft_freedom_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size)
|
||||
{
|
||||
divesoft_freedom_device_t *device = (divesoft_freedom_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));
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
divesoft_freedom_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
divesoft_freedom_device_t *device = (divesoft_freedom_device_t *) abstract;
|
||||
|
||||
// Enable progress notifications.
|
||||
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
|
||||
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
|
||||
|
||||
// Read the device information.
|
||||
unsigned char rsp_version[26] = {0};
|
||||
status = divesoft_freedom_download (device, MSG_VERSION, NULL, 0, rsp_version, sizeof(rsp_version));
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to read the device information.");
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
DEBUG (abstract->context, "Device: model=%u, hw=%u.%u, sw=%u.%u.%u.%u serial=%.16s",
|
||||
rsp_version[0],
|
||||
rsp_version[1], rsp_version[2],
|
||||
rsp_version[3], rsp_version[4], rsp_version[5],
|
||||
array_uint32_le (rsp_version + 6),
|
||||
rsp_version + 10);
|
||||
|
||||
// Emit a device info event.
|
||||
dc_event_devinfo_t devinfo;
|
||||
devinfo.model = rsp_version[0];
|
||||
devinfo.firmware = array_uint24_be (rsp_version + 3);
|
||||
devinfo.serial = array_convert_str2num (rsp_version + 10 + 5, 11);
|
||||
device_event_emit(abstract, DC_EVENT_DEVINFO, &devinfo);
|
||||
|
||||
// Allocate memory for the dive list.
|
||||
dc_buffer_t *divelist = dc_buffer_new (0);
|
||||
if (divelist == NULL) {
|
||||
status = DC_STATUS_NOMEMORY;
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
// Allocate memory for the download buffer.
|
||||
dc_buffer_t *buffer = dc_buffer_new (NRECORDS * (4 + FINGERPRINT_SIZE + HEADER_SIZE_V2));
|
||||
if (buffer == NULL) {
|
||||
status = DC_STATUS_NOMEMORY;
|
||||
goto error_free_divelist;
|
||||
}
|
||||
|
||||
// Record version and size.
|
||||
unsigned int version = 0;
|
||||
unsigned int headersize = 0;
|
||||
unsigned int recordsize = 0;
|
||||
|
||||
// Download the dive list.
|
||||
unsigned int ndives = 0;
|
||||
unsigned int total = 0;
|
||||
unsigned int maxsize = 0;
|
||||
unsigned int current = INVALID;
|
||||
while (1) {
|
||||
// Clear the buffer.
|
||||
dc_buffer_clear (buffer);
|
||||
|
||||
// Prepare the command.
|
||||
unsigned char cmd_list[6] = {0};
|
||||
array_uint32_le_set (cmd_list, current);
|
||||
cmd_list[4] = DIRECTION;
|
||||
cmd_list[5] = NRECORDS;
|
||||
|
||||
// Download the dive list records.
|
||||
message_t msg_list = MSG_ECHO;
|
||||
status = divesoft_freedom_transfer (device, &progress, MSG_DIVE_LIST, cmd_list, sizeof(cmd_list), &msg_list, buffer);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to download the dive list.");
|
||||
goto error_free_buffer;
|
||||
}
|
||||
|
||||
// Check the response message type.
|
||||
if (msg_list != MSG_DIVE_LIST_V1 && msg_list != MSG_DIVE_LIST_V2) {
|
||||
ERROR (abstract->context, "Unexpected response message (%u).", msg_list);
|
||||
status = DC_STATUS_PROTOCOL;
|
||||
goto error_free_buffer;
|
||||
}
|
||||
|
||||
// Store/check the version.
|
||||
if (version == 0) {
|
||||
version = msg_list;
|
||||
headersize = version == MSG_DIVE_LIST_V1 ?
|
||||
HEADER_SIZE_V1 : HEADER_SIZE_V2;
|
||||
recordsize = 4 + FINGERPRINT_SIZE + headersize;
|
||||
} else if (version != msg_list) {
|
||||
ERROR (abstract->context, "Unexpected response message (%u).", msg_list);
|
||||
status = DC_STATUS_PROTOCOL;
|
||||
goto error_free_buffer;
|
||||
}
|
||||
|
||||
const unsigned char *data = dc_buffer_get_data (buffer);
|
||||
size_t size = dc_buffer_get_size (buffer);
|
||||
|
||||
// Process the records.
|
||||
size_t offset = 0, count = 0;
|
||||
while (offset + recordsize <= size) {
|
||||
// Get the record data.
|
||||
unsigned int handle = array_uint32_le (data + offset);
|
||||
const unsigned char *fingerprint = data + offset + 4;
|
||||
const unsigned char *header = data + offset + 4 + FINGERPRINT_SIZE;
|
||||
|
||||
// Check the fingerprint data.
|
||||
if (memcmp (device->fingerprint, fingerprint, sizeof(device->fingerprint)) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the length of the dive.
|
||||
unsigned int nrecords = version == MSG_DIVE_LIST_V1 ?
|
||||
array_uint32_le (header + 16) & 0x3FFFF :
|
||||
array_uint32_le (header + 20);
|
||||
unsigned int length = headersize + nrecords * RECORD_SIZE;
|
||||
|
||||
// Calculate the total and maximum size.
|
||||
if (length > maxsize)
|
||||
maxsize = length;
|
||||
total += length;
|
||||
|
||||
// Set the handle for the next request.
|
||||
current = handle;
|
||||
|
||||
offset += recordsize;
|
||||
count++;
|
||||
ndives++;
|
||||
}
|
||||
|
||||
// Append the records to the dive list buffer.
|
||||
if (!dc_buffer_append (divelist, data, count * recordsize)) {
|
||||
ERROR (abstract->context, "Insufficient buffer space available.");
|
||||
status = DC_STATUS_NOMEMORY;
|
||||
goto error_free_buffer;
|
||||
}
|
||||
|
||||
// Stop downloading if there are no more records.
|
||||
if (count < NRECORDS)
|
||||
break;
|
||||
}
|
||||
|
||||
// Update and emit a progress event.
|
||||
progress.maximum = progress.current + total;
|
||||
device_event_emit(abstract, DC_EVENT_PROGRESS, &progress);
|
||||
|
||||
// Reserve memory for the largest dive.
|
||||
dc_buffer_reserve (buffer, maxsize);
|
||||
|
||||
const unsigned char *data = dc_buffer_get_data (divelist);
|
||||
size_t size = dc_buffer_get_size (divelist);
|
||||
|
||||
size_t offset = 0;
|
||||
while (offset + recordsize <= size) {
|
||||
// Get the record data.
|
||||
unsigned int handle = array_uint32_le (data + offset);
|
||||
const unsigned char *fingerprint = data + offset + 4;
|
||||
const unsigned char *header = data + offset + 4 + FINGERPRINT_SIZE;
|
||||
|
||||
// Get the length of the dive.
|
||||
unsigned int nrecords = version == MSG_DIVE_LIST_V1 ?
|
||||
array_uint32_le (header + 16) & 0x3FFFF :
|
||||
array_uint32_le (header + 20);
|
||||
unsigned int length = headersize + nrecords * RECORD_SIZE;
|
||||
|
||||
// Clear the buffer.
|
||||
dc_buffer_clear (buffer);
|
||||
|
||||
// Prepare the command.
|
||||
unsigned char cmd_dive[12] = {0};
|
||||
array_uint32_le_set (cmd_dive + 0, handle);
|
||||
array_uint32_le_set (cmd_dive + 4, 0);
|
||||
array_uint32_le_set (cmd_dive + 8, length);
|
||||
|
||||
// Download the dive.
|
||||
message_t msg_dive = MSG_ECHO;
|
||||
status = divesoft_freedom_transfer (device, &progress, MSG_DIVE_DATA, cmd_dive, sizeof(cmd_dive), &msg_dive, buffer);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to download the dive.");
|
||||
goto error_free_buffer;
|
||||
}
|
||||
|
||||
// Check the response message type.
|
||||
if (msg_dive != MSG_DIVE_DATA_RSP) {
|
||||
ERROR (abstract->context, "Unexpected response message (%u).", msg_dive);
|
||||
status = DC_STATUS_PROTOCOL;
|
||||
goto error_free_buffer;
|
||||
}
|
||||
|
||||
// Verify both dive headers are identical.
|
||||
if (dc_buffer_get_size (buffer) < headersize ||
|
||||
memcmp (header, dc_buffer_get_data (buffer), headersize) != 0) {
|
||||
ERROR (abstract->context, "Unexpected profile header.");
|
||||
status = DC_STATUS_PROTOCOL;
|
||||
goto error_free_buffer;
|
||||
}
|
||||
|
||||
if (callback && !callback (dc_buffer_get_data(buffer), dc_buffer_get_size(buffer), fingerprint, sizeof (device->fingerprint), userdata)) {
|
||||
break;
|
||||
}
|
||||
|
||||
offset += recordsize;
|
||||
}
|
||||
|
||||
error_free_buffer:
|
||||
dc_buffer_free (buffer);
|
||||
error_free_divelist:
|
||||
dc_buffer_free (divelist);
|
||||
error_exit:
|
||||
return status;
|
||||
}
|
||||
43
src/divesoft_freedom.h
Normal file
43
src/divesoft_freedom.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* libdivecomputer
|
||||
*
|
||||
* Copyright (C) 2023 Jan Matoušek, Jef Driesen
|
||||
*
|
||||
* 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 DIVESOFT_FREEDOM_H
|
||||
#define DIVESOFT_FREEDOM_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
|
||||
divesoft_freedom_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
divesoft_freedom_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* DIVESOFT_FREEDOM_H */
|
||||
1070
src/divesoft_freedom_parser.c
Normal file
1070
src/divesoft_freedom_parser.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -29,6 +29,7 @@
|
||||
#include "platform.h"
|
||||
#include "checksum.h"
|
||||
#include "array.h"
|
||||
#include "packet.h"
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &divesystem_idive_device_vtable)
|
||||
|
||||
@ -102,6 +103,7 @@ typedef struct divesystem_idive_device_t {
|
||||
static dc_status_t divesystem_idive_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
|
||||
static dc_status_t divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata);
|
||||
static dc_status_t divesystem_idive_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime);
|
||||
static dc_status_t divesystem_idive_device_close (dc_device_t *abstract);
|
||||
|
||||
static const dc_device_vtable_t divesystem_idive_device_vtable = {
|
||||
sizeof(divesystem_idive_device_t),
|
||||
@ -112,7 +114,7 @@ static const dc_device_vtable_t divesystem_idive_device_vtable = {
|
||||
NULL, /* dump */
|
||||
divesystem_idive_device_foreach, /* foreach */
|
||||
divesystem_idive_device_timesync, /* timesync */
|
||||
NULL /* close */
|
||||
divesystem_idive_device_close /* close */
|
||||
};
|
||||
|
||||
static const divesystem_idive_commands_t idive = {
|
||||
@ -152,6 +154,7 @@ divesystem_idive_device_open (dc_device_t **out, dc_context_t *context, dc_iostr
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
divesystem_idive_device_t *device = NULL;
|
||||
dc_transport_t transport = dc_iostream_get_transport (iostream);
|
||||
|
||||
if (out == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
@ -164,22 +167,32 @@ divesystem_idive_device_open (dc_device_t **out, dc_context_t *context, dc_iostr
|
||||
}
|
||||
|
||||
// Set the default values.
|
||||
device->iostream = iostream;
|
||||
memset (device->fingerprint, 0, sizeof (device->fingerprint));
|
||||
device->model = model;
|
||||
|
||||
// Create the packet stream.
|
||||
if (transport == DC_TRANSPORT_BLE) {
|
||||
status = dc_packet_open (&device->iostream, context, iostream, 244, 244);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to create the packet stream.");
|
||||
goto error_free;
|
||||
}
|
||||
} else {
|
||||
device->iostream = iostream;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (115200 8N1).
|
||||
status = dc_iostream_configure (device->iostream, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
goto error_free;
|
||||
goto error_free_iostream;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (1000ms).
|
||||
status = dc_iostream_set_timeout (device->iostream, 1000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
goto error_free;
|
||||
goto error_free_iostream;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
@ -190,11 +203,27 @@ divesystem_idive_device_open (dc_device_t **out, dc_context_t *context, dc_iostr
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_free_iostream:
|
||||
if (transport == DC_TRANSPORT_BLE) {
|
||||
dc_iostream_close (device->iostream);
|
||||
}
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
divesystem_idive_device_close (dc_device_t *abstract)
|
||||
{
|
||||
divesystem_idive_device_t *device = (divesystem_idive_device_t *) abstract;
|
||||
|
||||
// Close the packet stream.
|
||||
if (dc_iostream_get_transport (device->iostream) == DC_TRANSPORT_BLE) {
|
||||
return dc_iostream_close (device->iostream);
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
divesystem_idive_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size)
|
||||
@ -231,7 +260,7 @@ divesystem_idive_send (divesystem_idive_device_t *device, const unsigned char co
|
||||
packet[0] = START;
|
||||
packet[1] = csize;
|
||||
memcpy(packet + 2, command, csize);
|
||||
crc = checksum_crc16_ccitt (packet, csize + 2, 0xffff);
|
||||
crc = checksum_crc16_ccitt (packet, csize + 2, 0xffff, 0x0000);
|
||||
packet[csize + 2] = (crc >> 8) & 0xFF;
|
||||
packet[csize + 3] = (crc ) & 0xFF;
|
||||
|
||||
@ -292,7 +321,7 @@ divesystem_idive_receive (divesystem_idive_device_t *device, unsigned char answe
|
||||
|
||||
// Verify the checksum.
|
||||
unsigned short crc = array_uint16_be (packet + len + 2);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (packet, len + 2, 0xffff);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (packet, len + 2, 0xffff, 0x0000);
|
||||
if (crc != ccrc) {
|
||||
ERROR (abstract->context, "Unexpected packet checksum.");
|
||||
return DC_STATUS_PROTOCOL;
|
||||
|
||||
406
src/hdlc.c
Normal file
406
src/hdlc.c
Normal file
@ -0,0 +1,406 @@
|
||||
/*
|
||||
* libdivecomputer
|
||||
*
|
||||
* Copyright (C) 2023 Jef Driesen
|
||||
*
|
||||
* 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> // malloc, free
|
||||
|
||||
#include "hdlc.h"
|
||||
|
||||
#include "iostream-private.h"
|
||||
#include "common-private.h"
|
||||
#include "context-private.h"
|
||||
|
||||
#define END 0x7E
|
||||
#define ESC 0x7D
|
||||
#define ESC_BIT 0x20
|
||||
|
||||
static dc_status_t dc_hdlc_set_timeout (dc_iostream_t *abstract, int timeout);
|
||||
static dc_status_t dc_hdlc_set_break (dc_iostream_t *abstract, unsigned int value);
|
||||
static dc_status_t dc_hdlc_set_dtr (dc_iostream_t *abstract, unsigned int value);
|
||||
static dc_status_t dc_hdlc_set_rts (dc_iostream_t *abstract, unsigned int value);
|
||||
static dc_status_t dc_hdlc_get_lines (dc_iostream_t *abstract, unsigned int *value);
|
||||
static dc_status_t dc_hdlc_configure (dc_iostream_t *abstract, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
|
||||
static dc_status_t dc_hdlc_poll (dc_iostream_t *abstract, int timeout);
|
||||
static dc_status_t dc_hdlc_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual);
|
||||
static dc_status_t dc_hdlc_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual);
|
||||
static dc_status_t dc_hdlc_ioctl (dc_iostream_t *abstract, unsigned int request, void *data, size_t size);
|
||||
static dc_status_t dc_hdlc_flush (dc_iostream_t *abstract);
|
||||
static dc_status_t dc_hdlc_purge (dc_iostream_t *abstract, dc_direction_t direction);
|
||||
static dc_status_t dc_hdlc_sleep (dc_iostream_t *abstract, unsigned int milliseconds);
|
||||
static dc_status_t dc_hdlc_close (dc_iostream_t *abstract);
|
||||
|
||||
typedef struct dc_hdlc_t {
|
||||
/* Base class. */
|
||||
dc_iostream_t base;
|
||||
/* Internal state. */
|
||||
dc_context_t *context;
|
||||
dc_iostream_t *iostream;
|
||||
unsigned char *rbuf;
|
||||
unsigned char *wbuf;
|
||||
size_t rbuf_size;
|
||||
size_t rbuf_offset;
|
||||
size_t rbuf_available;
|
||||
size_t wbuf_size;
|
||||
size_t wbuf_offset;
|
||||
} dc_hdlc_t;
|
||||
|
||||
static const dc_iostream_vtable_t dc_hdlc_vtable = {
|
||||
sizeof(dc_hdlc_t),
|
||||
dc_hdlc_set_timeout, /* set_timeout */
|
||||
dc_hdlc_set_break, /* set_break */
|
||||
dc_hdlc_set_dtr, /* set_dtr */
|
||||
dc_hdlc_set_rts, /* set_rts */
|
||||
dc_hdlc_get_lines, /* get_lines */
|
||||
NULL, /* get_available */
|
||||
dc_hdlc_configure, /* configure */
|
||||
dc_hdlc_poll, /* poll */
|
||||
dc_hdlc_read, /* read */
|
||||
dc_hdlc_write, /* write */
|
||||
dc_hdlc_ioctl, /* ioctl */
|
||||
dc_hdlc_flush, /* flush */
|
||||
dc_hdlc_purge, /* purge */
|
||||
dc_hdlc_sleep, /* sleep */
|
||||
dc_hdlc_close, /* close */
|
||||
};
|
||||
|
||||
dc_status_t
|
||||
dc_hdlc_open (dc_iostream_t **out, dc_context_t *context, dc_iostream_t *base, size_t isize, size_t osize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_hdlc_t *hdlc = NULL;
|
||||
|
||||
if (out == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
if (base == NULL || isize == 0 || osize == 0)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
dc_transport_t transport = dc_iostream_get_transport (base);
|
||||
|
||||
// Allocate memory.
|
||||
hdlc = (dc_hdlc_t *) dc_iostream_allocate (NULL, &dc_hdlc_vtable, transport);
|
||||
if (hdlc == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
status = DC_STATUS_NOMEMORY;
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
// Allocate the read buffer.
|
||||
hdlc->rbuf = malloc (isize);
|
||||
if (hdlc->rbuf == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
status = DC_STATUS_NOMEMORY;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Allocate the write buffer.
|
||||
hdlc->wbuf = malloc (osize);
|
||||
if (hdlc->wbuf == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
status = DC_STATUS_NOMEMORY;
|
||||
goto error_free_rbuf;
|
||||
}
|
||||
|
||||
hdlc->context = context;
|
||||
hdlc->iostream = base;
|
||||
hdlc->rbuf_size = isize;
|
||||
hdlc->rbuf_offset = 0;
|
||||
hdlc->rbuf_available = 0;
|
||||
hdlc->wbuf_size = osize;
|
||||
hdlc->wbuf_offset = 0;
|
||||
|
||||
*out = (dc_iostream_t *) hdlc;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_free_rbuf:
|
||||
free (hdlc->rbuf);
|
||||
error_free:
|
||||
dc_iostream_deallocate ((dc_iostream_t *) hdlc);
|
||||
error_exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_hdlc_set_timeout (dc_iostream_t *abstract, int timeout)
|
||||
{
|
||||
dc_hdlc_t *hdlc = (dc_hdlc_t *) abstract;
|
||||
|
||||
return dc_iostream_set_timeout (hdlc->iostream, timeout);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_hdlc_set_break (dc_iostream_t *abstract, unsigned int value)
|
||||
{
|
||||
dc_hdlc_t *hdlc = (dc_hdlc_t *) abstract;
|
||||
|
||||
return dc_iostream_set_break (hdlc->iostream, value);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_hdlc_set_dtr (dc_iostream_t *abstract, unsigned int value)
|
||||
{
|
||||
dc_hdlc_t *hdlc = (dc_hdlc_t *) abstract;
|
||||
|
||||
return dc_iostream_set_dtr (hdlc->iostream, value);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_hdlc_set_rts (dc_iostream_t *abstract, unsigned int value)
|
||||
{
|
||||
dc_hdlc_t *hdlc = (dc_hdlc_t *) abstract;
|
||||
|
||||
return dc_iostream_set_rts (hdlc->iostream, value);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_hdlc_get_lines (dc_iostream_t *abstract, unsigned int *value)
|
||||
{
|
||||
dc_hdlc_t *hdlc = (dc_hdlc_t *) abstract;
|
||||
|
||||
return dc_iostream_get_lines (hdlc->iostream, value);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_hdlc_configure (dc_iostream_t *abstract, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol)
|
||||
{
|
||||
dc_hdlc_t *hdlc = (dc_hdlc_t *) abstract;
|
||||
|
||||
return dc_iostream_configure (hdlc->iostream, baudrate, databits, parity, stopbits, flowcontrol);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_hdlc_poll (dc_iostream_t *abstract, int timeout)
|
||||
{
|
||||
dc_hdlc_t *hdlc = (dc_hdlc_t *) abstract;
|
||||
|
||||
if (hdlc->rbuf_available) {
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return dc_iostream_poll (hdlc->iostream, timeout);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_hdlc_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_hdlc_t *hdlc = (dc_hdlc_t *) abstract;
|
||||
size_t nbytes = 0;
|
||||
|
||||
unsigned int initialized = 0;
|
||||
unsigned int escaped = 0;
|
||||
|
||||
while (1) {
|
||||
if (hdlc->rbuf_available == 0) {
|
||||
// Read a packet into the cache.
|
||||
size_t len = 0;
|
||||
status = dc_iostream_read (hdlc->iostream, hdlc->rbuf, hdlc->rbuf_size, &len);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdlc->rbuf_available = len;
|
||||
hdlc->rbuf_offset = 0;
|
||||
}
|
||||
|
||||
while (hdlc->rbuf_available) {
|
||||
unsigned char c = hdlc->rbuf[hdlc->rbuf_offset];
|
||||
hdlc->rbuf_offset++;
|
||||
hdlc->rbuf_available--;
|
||||
|
||||
if (c == END) {
|
||||
if (escaped) {
|
||||
ERROR (hdlc->context, "HDLC frame escaped the special character %02x.", c);
|
||||
status = DC_STATUS_IO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (initialized) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
initialized = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!initialized) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == ESC) {
|
||||
if (escaped) {
|
||||
ERROR (hdlc->context, "HDLC frame escaped the special character %02x.", c);
|
||||
status = DC_STATUS_IO;
|
||||
goto out;
|
||||
}
|
||||
escaped = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (escaped) {
|
||||
c ^= ESC_BIT;
|
||||
escaped = 0;
|
||||
}
|
||||
|
||||
if (nbytes < size)
|
||||
((unsigned char *)data)[nbytes] = c;
|
||||
nbytes++;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (nbytes > size) {
|
||||
ERROR (hdlc->context, "HDLC frame is too large (" DC_PRINTF_SIZE " " DC_PRINTF_SIZE ").", nbytes, size);
|
||||
dc_status_set_error (&status, DC_STATUS_IO);
|
||||
nbytes = size;
|
||||
}
|
||||
|
||||
if (actual)
|
||||
*actual = nbytes;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_hdlc_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_hdlc_t *hdlc = (dc_hdlc_t *) abstract;
|
||||
size_t nbytes = 0;
|
||||
|
||||
// Clear the buffer.
|
||||
hdlc->wbuf_offset = 0;
|
||||
|
||||
// Start of the packet.
|
||||
hdlc->wbuf[hdlc->wbuf_offset++] = END;
|
||||
|
||||
// Flush the buffer if necessary.
|
||||
if (hdlc->wbuf_offset >= hdlc->wbuf_size) {
|
||||
status = dc_iostream_write (hdlc->iostream, hdlc->wbuf, hdlc->wbuf_offset, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdlc->wbuf_offset = 0;
|
||||
}
|
||||
|
||||
while (nbytes < size) {
|
||||
unsigned char c = ((const unsigned char *) data)[nbytes];
|
||||
|
||||
if (c == END || c == ESC) {
|
||||
// Append the escape character.
|
||||
hdlc->wbuf[hdlc->wbuf_offset++] = ESC;
|
||||
|
||||
// Flush the buffer if necessary.
|
||||
if (hdlc->wbuf_offset >= hdlc->wbuf_size) {
|
||||
status = dc_iostream_write (hdlc->iostream, hdlc->wbuf, hdlc->wbuf_offset, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdlc->wbuf_offset = 0;
|
||||
}
|
||||
|
||||
// Escape the character.
|
||||
c ^= ESC_BIT;
|
||||
}
|
||||
|
||||
// Append the character.
|
||||
hdlc->wbuf[hdlc->wbuf_offset++] = c;
|
||||
|
||||
// Flush the buffer if necessary.
|
||||
if (hdlc->wbuf_offset >= hdlc->wbuf_size) {
|
||||
status = dc_iostream_write (hdlc->iostream, hdlc->wbuf, hdlc->wbuf_offset, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdlc->wbuf_offset = 0;
|
||||
}
|
||||
|
||||
nbytes++;
|
||||
}
|
||||
|
||||
// End of the packet.
|
||||
hdlc->wbuf[hdlc->wbuf_offset++] = END;
|
||||
|
||||
// Flush the buffer.
|
||||
status = dc_iostream_write (hdlc->iostream, hdlc->wbuf, hdlc->wbuf_offset, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdlc->wbuf_offset = 0;
|
||||
|
||||
out:
|
||||
if (actual)
|
||||
*actual = nbytes;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_hdlc_ioctl (dc_iostream_t *abstract, unsigned int request, void *data, size_t size)
|
||||
{
|
||||
dc_hdlc_t *hdlc = (dc_hdlc_t *) abstract;
|
||||
|
||||
return dc_iostream_ioctl (hdlc->iostream, request, data, size);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_hdlc_flush (dc_iostream_t *abstract)
|
||||
{
|
||||
dc_hdlc_t *hdlc = (dc_hdlc_t *) abstract;
|
||||
|
||||
return dc_iostream_flush (hdlc->iostream);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_hdlc_purge (dc_iostream_t *abstract, dc_direction_t direction)
|
||||
{
|
||||
dc_hdlc_t *hdlc = (dc_hdlc_t *) abstract;
|
||||
|
||||
if (direction & DC_DIRECTION_INPUT) {
|
||||
hdlc->rbuf_available = 0;
|
||||
hdlc->rbuf_offset = 0;
|
||||
}
|
||||
|
||||
return dc_iostream_purge (hdlc->iostream, direction);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_hdlc_sleep (dc_iostream_t *abstract, unsigned int milliseconds)
|
||||
{
|
||||
dc_hdlc_t *hdlc = (dc_hdlc_t *) abstract;
|
||||
|
||||
return dc_iostream_sleep (hdlc->iostream, milliseconds);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_hdlc_close (dc_iostream_t *abstract)
|
||||
{
|
||||
dc_hdlc_t *hdlc = (dc_hdlc_t *) abstract;
|
||||
|
||||
free (hdlc->wbuf);
|
||||
free (hdlc->rbuf);
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
50
src/hdlc.h
Normal file
50
src/hdlc.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* libdivecomputer
|
||||
*
|
||||
* Copyright (C) 2023 Jef Driesen
|
||||
*
|
||||
* 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 DC_HDLC_H
|
||||
#define DC_HDLC_H
|
||||
|
||||
#include <libdivecomputer/common.h>
|
||||
#include <libdivecomputer/context.h>
|
||||
#include <libdivecomputer/iostream.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* Create a HDLC I/O stream layered on top of another base I/O stream.
|
||||
*
|
||||
* @param[out] iostream A location to store the HDLC I/O stream.
|
||||
* @param[in] context A valid context.
|
||||
* @param[in] base A valid I/O stream.
|
||||
* @param[in] isize The input packet size in bytes.
|
||||
* @param[in] osize The output packet size in bytes.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_hdlc_open (dc_iostream_t **iostream, dc_context_t *context, dc_iostream_t *base, size_t isize, size_t osize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* DC_HDLC_H */
|
||||
@ -30,6 +30,7 @@
|
||||
#include "array.h"
|
||||
#include "aes.h"
|
||||
#include "platform.h"
|
||||
#include "packet.h"
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &hw_ostc3_device_vtable)
|
||||
|
||||
@ -119,9 +120,6 @@ typedef struct hw_ostc3_device_t {
|
||||
unsigned int firmware;
|
||||
unsigned char fingerprint[5];
|
||||
hw_ostc3_state_t state;
|
||||
unsigned char cache[244];
|
||||
unsigned int available;
|
||||
unsigned int offset;
|
||||
} hw_ostc3_device_t;
|
||||
|
||||
typedef struct hw_ostc3_logbook_t {
|
||||
@ -207,41 +205,20 @@ static dc_status_t
|
||||
hw_ostc3_read (hw_ostc3_device_t *device, dc_event_progress_t *progress, unsigned char data[], size_t size)
|
||||
{
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
dc_transport_t transport = dc_iostream_get_transport(device->iostream);
|
||||
|
||||
size_t nbytes = 0;
|
||||
while (nbytes < size) {
|
||||
if (transport == DC_TRANSPORT_BLE) {
|
||||
if (device->available == 0) {
|
||||
// Read a packet into the cache.
|
||||
size_t len = 0;
|
||||
rc = dc_iostream_read (device->iostream, device->cache, sizeof(device->cache), &len);
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
device->available = len;
|
||||
device->offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the minimum packet size.
|
||||
size_t length = (transport == DC_TRANSPORT_BLE) ? device->available : 1024;
|
||||
size_t length = 1024;
|
||||
|
||||
// Limit the packet size to the total size.
|
||||
if (nbytes + length > size)
|
||||
length = size - nbytes;
|
||||
|
||||
if (transport == DC_TRANSPORT_BLE) {
|
||||
// Copy the data from the cached packet.
|
||||
memcpy (data + nbytes, device->cache + device->offset, length);
|
||||
device->available -= length;
|
||||
device->offset += length;
|
||||
} else {
|
||||
// Read the packet.
|
||||
rc = dc_iostream_read (device->iostream, data + nbytes, length, NULL);
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
}
|
||||
// Read the packet.
|
||||
rc = dc_iostream_read (device->iostream, data + nbytes, length, NULL);
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
// Update and emit a progress event.
|
||||
if (progress) {
|
||||
@ -259,12 +236,11 @@ static dc_status_t
|
||||
hw_ostc3_write (hw_ostc3_device_t *device, dc_event_progress_t *progress, const unsigned char data[], size_t size)
|
||||
{
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
dc_transport_t transport = dc_iostream_get_transport(device->iostream);
|
||||
|
||||
size_t nbytes = 0;
|
||||
while (nbytes < size) {
|
||||
// Set the maximum packet size.
|
||||
size_t length = (transport == DC_TRANSPORT_BLE) ? sizeof(device->cache) : 64;
|
||||
size_t length = 1024;
|
||||
|
||||
// Limit the packet size to the total size.
|
||||
if (nbytes + length > size)
|
||||
@ -313,7 +289,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
|
||||
|
||||
// Send the command.
|
||||
unsigned char command[1] = {cmd};
|
||||
status = hw_ostc3_write (device, NULL, command, sizeof (command));
|
||||
status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return status;
|
||||
@ -321,7 +297,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
|
||||
|
||||
// Read the echo.
|
||||
unsigned char echo[1] = {0};
|
||||
status = hw_ostc3_read (device, NULL, echo, sizeof (echo));
|
||||
status = dc_iostream_read (device->iostream, echo, sizeof (echo), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the echo.");
|
||||
return status;
|
||||
@ -407,14 +383,14 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
|
||||
}
|
||||
}
|
||||
|
||||
if (delay && device->available == 0) {
|
||||
if (delay) {
|
||||
dc_iostream_poll (device->iostream, delay);
|
||||
}
|
||||
|
||||
if (cmd != EXIT) {
|
||||
// Read the ready byte.
|
||||
unsigned char answer[1] = {0};
|
||||
status = hw_ostc3_read (device, NULL, answer, sizeof (answer));
|
||||
status = dc_iostream_read (device->iostream, answer, sizeof (answer), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the ready byte.");
|
||||
return status;
|
||||
@ -439,6 +415,7 @@ hw_ostc3_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t *i
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
hw_ostc3_device_t *device = NULL;
|
||||
dc_transport_t transport = dc_iostream_get_transport (iostream);
|
||||
|
||||
if (out == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
@ -451,29 +428,36 @@ hw_ostc3_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t *i
|
||||
}
|
||||
|
||||
// Set the default values.
|
||||
device->iostream = iostream;
|
||||
device->hardware = INVALID;
|
||||
device->feature = 0;
|
||||
device->model = 0;
|
||||
device->serial = 0;
|
||||
device->firmware = 0;
|
||||
memset (device->fingerprint, 0, sizeof (device->fingerprint));
|
||||
memset (device->cache, 0, sizeof (device->cache));
|
||||
device->available = 0;
|
||||
device->offset = 0;
|
||||
|
||||
// Create the packet stream.
|
||||
if (transport == DC_TRANSPORT_BLE) {
|
||||
status = dc_packet_open (&device->iostream, context, iostream, 244, 20);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to create the packet stream.");
|
||||
goto error_free;
|
||||
}
|
||||
} else {
|
||||
device->iostream = iostream;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (115200 8N1).
|
||||
status = dc_iostream_configure (device->iostream, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
goto error_free;
|
||||
goto error_free_iostream;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (3000ms).
|
||||
status = dc_iostream_set_timeout (device->iostream, 3000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
goto error_free;
|
||||
goto error_free_iostream;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
@ -486,6 +470,10 @@ hw_ostc3_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t *i
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_free_iostream:
|
||||
if (transport == DC_TRANSPORT_BLE) {
|
||||
dc_iostream_close (device->iostream);
|
||||
}
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
@ -548,14 +536,14 @@ hw_ostc3_device_init_service (hw_ostc3_device_t *device)
|
||||
unsigned char answer[5] = {0};
|
||||
|
||||
// Send the command and service key.
|
||||
status = hw_ostc3_write (device, NULL, command, sizeof (command));
|
||||
status = dc_iostream_write (device->iostream, command, sizeof (command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return status;
|
||||
}
|
||||
|
||||
// Read the response.
|
||||
status = hw_ostc3_read (device, NULL, answer, sizeof (answer));
|
||||
status = dc_iostream_read (device->iostream, answer, sizeof (answer), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return status;
|
||||
@ -656,6 +644,15 @@ hw_ostc3_device_close (dc_device_t *abstract)
|
||||
}
|
||||
}
|
||||
|
||||
// Close the packet stream.
|
||||
if (dc_iostream_get_transport (device->iostream) == DC_TRANSPORT_BLE) {
|
||||
rc = dc_iostream_close (device->iostream);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to close the packet stream.");
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
68
src/libdivecomputer.rc
Normal file
68
src/libdivecomputer.rc
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* libdivecomputer
|
||||
*
|
||||
* Copyright (C) 2010 Jef Driesen
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winver.h>
|
||||
|
||||
#include <libdivecomputer/version.h>
|
||||
|
||||
#ifdef HAVE_VERSION_SUFFIX
|
||||
#include "revision.h"
|
||||
#endif
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION DC_VERSION_MAJOR,DC_VERSION_MINOR,DC_VERSION_MICRO,0
|
||||
PRODUCTVERSION DC_VERSION_MAJOR,DC_VERSION_MINOR,DC_VERSION_MICRO,0
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef HAVE_VERSION_SUFFIX
|
||||
FILEFLAGS VS_FF_PRERELEASE
|
||||
#else
|
||||
FILEFLAGS 0
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904B0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "The libdivecomputer developers"
|
||||
VALUE "FileDescription", "A library for communication with various dive computers."
|
||||
VALUE "FileVersion", DC_VERSION
|
||||
VALUE "InternalName", "libdivecomputer"
|
||||
VALUE "LegalCopyright", "Copyright © 2010 Jef Driesen"
|
||||
VALUE "OriginalFilename", "libdivecomputer.dll"
|
||||
VALUE "ProductName", "libdivecomputer"
|
||||
VALUE "ProductVersion", DC_VERSION
|
||||
#ifdef HAVE_VERSION_SUFFIX
|
||||
VALUE "Comments", DC_VERSION_REVISION
|
||||
#endif
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 1033, 1200
|
||||
END
|
||||
END
|
||||
@ -1,45 +0,0 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winver.h>
|
||||
|
||||
#ifdef HAVE_VERSION_SUFFIX
|
||||
#include "revision.h"
|
||||
#endif
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION @DC_VERSION_MAJOR@,@DC_VERSION_MINOR@,@DC_VERSION_MICRO@,0
|
||||
PRODUCTVERSION @DC_VERSION_MAJOR@,@DC_VERSION_MINOR@,@DC_VERSION_MICRO@,0
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef HAVE_VERSION_SUFFIX
|
||||
FILEFLAGS VS_FF_PRERELEASE
|
||||
#else
|
||||
FILEFLAGS 0
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904B0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "The libdivecomputer developers"
|
||||
VALUE "FileDescription", "A library for communication with various dive computers."
|
||||
VALUE "FileVersion", "@VERSION@"
|
||||
VALUE "InternalName", "libdivecomputer"
|
||||
VALUE "LegalCopyright", "Copyright © 2010 Jef Driesen"
|
||||
VALUE "OriginalFilename", "libdivecomputer.dll"
|
||||
VALUE "ProductName", "libdivecomputer"
|
||||
VALUE "ProductVersion", "@VERSION@"
|
||||
#ifdef HAVE_VERSION_SUFFIX
|
||||
VALUE "Comments", DC_VERSION_REVISION
|
||||
#endif
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 1033, 1200
|
||||
END
|
||||
END
|
||||
@ -158,7 +158,7 @@ liquivision_lynx_recv (liquivision_lynx_device_t *device, unsigned char data[],
|
||||
|
||||
// Verify the checksum.
|
||||
unsigned short crc = array_uint16_be (packet + 1 + size);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (packet + 1, size, 0xffff);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (packet + 1, size, 0xffff, 0x0000);
|
||||
if (crc != ccrc) {
|
||||
ERROR (abstract->context, "Unexpected answer checksum (%04x %04x).", crc, ccrc);
|
||||
return DC_STATUS_PROTOCOL;
|
||||
@ -528,7 +528,7 @@ liquivision_lynx_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
|
||||
memcpy (header + 0, device->info + 2, 4);
|
||||
memcpy (header + 4, logbook + offset + 4, headersize - 4);
|
||||
unsigned int crc = array_uint32_le (logbook + offset + 0);
|
||||
unsigned int ccrc = checksum_crc32b (header, headersize - unused);
|
||||
unsigned int ccrc = checksum_crc32 (header, headersize - unused);
|
||||
if (crc != ccrc) {
|
||||
WARNING (abstract->context, "Invalid dive checksum (%08x %08x)", crc, ccrc);
|
||||
status = DC_STATUS_DATAFORMAT;
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include "array.h"
|
||||
#include "rbstream.h"
|
||||
#include "platform.h"
|
||||
#include "packet.h"
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &mares_iconhd_device_vtable)
|
||||
|
||||
@ -93,9 +94,6 @@ typedef struct mares_iconhd_device_t {
|
||||
unsigned char version[140];
|
||||
unsigned int model;
|
||||
unsigned int packetsize;
|
||||
unsigned char cache[20];
|
||||
unsigned int available;
|
||||
unsigned int offset;
|
||||
unsigned int splitcommand;
|
||||
} mares_iconhd_device_t;
|
||||
|
||||
@ -103,6 +101,7 @@ static dc_status_t mares_iconhd_device_set_fingerprint (dc_device_t *abstract, c
|
||||
static dc_status_t mares_iconhd_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size);
|
||||
static dc_status_t mares_iconhd_device_dump (dc_device_t *abstract, dc_buffer_t *buffer);
|
||||
static dc_status_t mares_iconhd_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata);
|
||||
static dc_status_t mares_iconhd_device_close (dc_device_t *abstract);
|
||||
|
||||
static const dc_device_vtable_t mares_iconhd_device_vtable = {
|
||||
sizeof(mares_iconhd_device_t),
|
||||
@ -113,7 +112,7 @@ static const dc_device_vtable_t mares_iconhd_device_vtable = {
|
||||
mares_iconhd_device_dump, /* dump */
|
||||
mares_iconhd_device_foreach, /* foreach */
|
||||
NULL, /* timesync */
|
||||
NULL /* close */
|
||||
mares_iconhd_device_close /* close */
|
||||
};
|
||||
|
||||
static const mares_iconhd_layout_t mares_iconhd_layout = {
|
||||
@ -178,78 +177,6 @@ mares_iconhd_get_model (mares_iconhd_device_t *device)
|
||||
return model;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
mares_iconhd_read (mares_iconhd_device_t *device, unsigned char data[], size_t size)
|
||||
{
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
dc_transport_t transport = dc_iostream_get_transport(device->iostream);
|
||||
|
||||
size_t nbytes = 0;
|
||||
while (nbytes < size) {
|
||||
if (transport == DC_TRANSPORT_BLE) {
|
||||
if (device->available == 0) {
|
||||
// Read a packet into the cache.
|
||||
size_t len = 0;
|
||||
rc = dc_iostream_read (device->iostream, device->cache, sizeof(device->cache), &len);
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
device->available = len;
|
||||
device->offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the minimum packet size.
|
||||
size_t length = (transport == DC_TRANSPORT_BLE) ? device->available : size - nbytes;
|
||||
|
||||
// Limit the packet size to the total size.
|
||||
if (nbytes + length > size)
|
||||
length = size - nbytes;
|
||||
|
||||
if (transport == DC_TRANSPORT_BLE) {
|
||||
// Copy the data from the cached packet.
|
||||
memcpy (data + nbytes, device->cache + device->offset, length);
|
||||
device->available -= length;
|
||||
device->offset += length;
|
||||
} else {
|
||||
// Read the packet.
|
||||
rc = dc_iostream_read (device->iostream, data + nbytes, length, &length);
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
}
|
||||
|
||||
nbytes += length;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
mares_iconhd_write (mares_iconhd_device_t *device, const unsigned char data[], size_t size)
|
||||
{
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
dc_transport_t transport = dc_iostream_get_transport(device->iostream);
|
||||
|
||||
size_t nbytes = 0;
|
||||
while (nbytes < size) {
|
||||
// Set the maximum packet size.
|
||||
size_t length = (transport == DC_TRANSPORT_BLE) ? sizeof(device->cache) : size - nbytes;
|
||||
|
||||
// Limit the packet size to the total size.
|
||||
if (nbytes + length > size)
|
||||
length = size - nbytes;
|
||||
|
||||
// Write the packet.
|
||||
rc = dc_iostream_write (device->iostream, data + nbytes, length, &length);
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
nbytes += length;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
mares_iconhd_packet (mares_iconhd_device_t *device,
|
||||
const unsigned char command[], unsigned int csize,
|
||||
@ -267,7 +194,7 @@ mares_iconhd_packet (mares_iconhd_device_t *device,
|
||||
split_csize = device->splitcommand ? 2 : csize;
|
||||
|
||||
// Send the command header to the dive computer.
|
||||
status = mares_iconhd_write (device, command, split_csize);
|
||||
status = dc_iostream_write (device->iostream, command, split_csize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return status;
|
||||
@ -275,7 +202,7 @@ mares_iconhd_packet (mares_iconhd_device_t *device,
|
||||
|
||||
// Receive the header byte.
|
||||
unsigned char header[1] = {0};
|
||||
status = mares_iconhd_read (device, header, sizeof (header));
|
||||
status = dc_iostream_read (device->iostream, header, sizeof (header), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return status;
|
||||
@ -289,7 +216,7 @@ mares_iconhd_packet (mares_iconhd_device_t *device,
|
||||
|
||||
// Send any remaining command payload to the dive computer.
|
||||
if (csize > split_csize) {
|
||||
status = mares_iconhd_write (device, command + split_csize, csize - split_csize);
|
||||
status = dc_iostream_write (device->iostream, command + split_csize, csize - split_csize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return status;
|
||||
@ -297,7 +224,7 @@ mares_iconhd_packet (mares_iconhd_device_t *device,
|
||||
}
|
||||
|
||||
// Read the packet.
|
||||
status = mares_iconhd_read (device, answer, asize);
|
||||
status = dc_iostream_read (device->iostream, answer, asize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return status;
|
||||
@ -305,7 +232,7 @@ mares_iconhd_packet (mares_iconhd_device_t *device,
|
||||
|
||||
// Receive the trailer byte.
|
||||
unsigned char trailer[1] = {0};
|
||||
status = mares_iconhd_read (device, trailer, sizeof (trailer));
|
||||
status = dc_iostream_read (device->iostream, trailer, sizeof (trailer), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return status;
|
||||
@ -338,8 +265,6 @@ mares_iconhd_transfer (mares_iconhd_device_t *device, const unsigned char comman
|
||||
// Discard any garbage bytes.
|
||||
dc_iostream_sleep (device->iostream, 100);
|
||||
dc_iostream_purge (device->iostream, DC_DIRECTION_INPUT);
|
||||
device->available = 0;
|
||||
device->offset = 0;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
@ -463,6 +388,7 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
mares_iconhd_device_t *device = NULL;
|
||||
dc_transport_t transport = dc_iostream_get_transport (iostream);
|
||||
|
||||
if (out == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
@ -475,16 +401,23 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
|
||||
}
|
||||
|
||||
// Set the default values.
|
||||
device->iostream = iostream;
|
||||
device->layout = NULL;
|
||||
memset (device->fingerprint, 0, sizeof (device->fingerprint));
|
||||
device->fingerprint_size = sizeof (device->fingerprint);
|
||||
memset (device->version, 0, sizeof (device->version));
|
||||
device->model = 0;
|
||||
device->packetsize = 0;
|
||||
memset (device->cache, 0, sizeof (device->cache));
|
||||
device->available = 0;
|
||||
device->offset = 0;
|
||||
|
||||
// Create the packet stream.
|
||||
if (transport == DC_TRANSPORT_BLE) {
|
||||
status = dc_packet_open (&device->iostream, context, iostream, 20, 20);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to create the packet stream.");
|
||||
goto error_free;
|
||||
}
|
||||
} else {
|
||||
device->iostream = iostream;
|
||||
}
|
||||
|
||||
/*
|
||||
* At least the Mares Matrix needs the command to be split into
|
||||
@ -499,28 +432,28 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
|
||||
status = dc_iostream_configure (device->iostream, 115200, 8, DC_PARITY_EVEN, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the terminal attributes.");
|
||||
goto error_free;
|
||||
goto error_free_iostream;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (3000 ms).
|
||||
status = dc_iostream_set_timeout (device->iostream, 3000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
goto error_free;
|
||||
goto error_free_iostream;
|
||||
}
|
||||
|
||||
// Clear the DTR line.
|
||||
status = dc_iostream_set_dtr (device->iostream, 0);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to clear the DTR line.");
|
||||
goto error_free;
|
||||
goto error_free_iostream;
|
||||
}
|
||||
|
||||
// Clear the RTS line.
|
||||
status = dc_iostream_set_rts (device->iostream, 0);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to clear the RTS line.");
|
||||
goto error_free;
|
||||
goto error_free_iostream;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
@ -531,7 +464,7 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
|
||||
status = mares_iconhd_transfer (device, command, sizeof (command),
|
||||
device->version, sizeof (device->version));
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
goto error_free;
|
||||
goto error_free_iostream;
|
||||
}
|
||||
|
||||
// Autodetect the model using the version packet.
|
||||
@ -619,12 +552,31 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
|
||||
error_free_iostream:
|
||||
if (transport == DC_TRANSPORT_BLE) {
|
||||
dc_iostream_close (device->iostream);
|
||||
}
|
||||
error_free:
|
||||
dc_device_deallocate ((dc_device_t *) device);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
mares_iconhd_device_close (dc_device_t *abstract)
|
||||
{
|
||||
mares_iconhd_device_t *device = (mares_iconhd_device_t *) abstract;
|
||||
|
||||
// Close the packet stream.
|
||||
if (dc_iostream_get_transport (device->iostream) == DC_TRANSPORT_BLE) {
|
||||
return dc_iostream_close (device->iostream);
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
mares_iconhd_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size)
|
||||
{
|
||||
|
||||
@ -299,7 +299,7 @@ mares_genius_isvalid (const unsigned char data[], size_t size, unsigned int type
|
||||
}
|
||||
|
||||
unsigned short crc = array_uint16_le(data + size - 6);
|
||||
unsigned short ccrc = checksum_crc16_ccitt(data + 4, size - 10, 0x0000);
|
||||
unsigned short ccrc = checksum_crc16_ccitt(data + 4, size - 10, 0x0000, 0x0000);
|
||||
if (crc != ccrc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include "context-private.h"
|
||||
#include "device-private.h"
|
||||
#include "array.h"
|
||||
#include "packet.h"
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &mclean_extreme_device_vtable)
|
||||
|
||||
@ -391,6 +392,7 @@ mclean_extreme_device_open(dc_device_t **out, dc_context_t *context, dc_iostream
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
mclean_extreme_device_t *device = NULL;
|
||||
dc_transport_t transport = dc_iostream_get_transport (iostream);
|
||||
|
||||
if (out == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
@ -403,21 +405,31 @@ mclean_extreme_device_open(dc_device_t **out, dc_context_t *context, dc_iostream
|
||||
}
|
||||
|
||||
// Set the default values.
|
||||
device->iostream = iostream;
|
||||
memset(device->fingerprint, 0, sizeof(device->fingerprint));
|
||||
|
||||
// Create the packet stream.
|
||||
if (transport == DC_TRANSPORT_BLE) {
|
||||
status = dc_packet_open (&device->iostream, context, iostream, 244, 244);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to create the packet stream.");
|
||||
goto error_free;
|
||||
}
|
||||
} else {
|
||||
device->iostream = iostream;
|
||||
}
|
||||
|
||||
// Set the serial communication protocol (115200 8N1).
|
||||
status = dc_iostream_configure(device->iostream, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR(context, "Failed to set the terminal attributes.");
|
||||
goto error_free;
|
||||
goto error_free_iostream;
|
||||
}
|
||||
|
||||
// Set the timeout for receiving data (1000ms).
|
||||
status = dc_iostream_set_timeout(device->iostream, 1000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR(context, "Failed to set the timeout.");
|
||||
goto error_free;
|
||||
goto error_free_iostream;
|
||||
}
|
||||
|
||||
// Make sure everything is in a sane state.
|
||||
@ -428,6 +440,10 @@ mclean_extreme_device_open(dc_device_t **out, dc_context_t *context, dc_iostream
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_free_iostream:
|
||||
if (transport == DC_TRANSPORT_BLE) {
|
||||
dc_iostream_close (device->iostream);
|
||||
}
|
||||
error_free:
|
||||
dc_device_deallocate((dc_device_t *)device);
|
||||
return status;
|
||||
@ -438,14 +454,24 @@ mclean_extreme_device_close(dc_device_t *abstract)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
mclean_extreme_device_t *device = (mclean_extreme_device_t *)abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
status = mclean_extreme_send(device, CMD_CLOSE, NULL, 0);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
rc = mclean_extreme_send(device, CMD_CLOSE, NULL, 0);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR(abstract->context, "Failed to send the exit command.");
|
||||
return status;
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
// Close the packet stream.
|
||||
if (dc_iostream_get_transport (device->iostream) == DC_TRANSPORT_BLE) {
|
||||
rc = dc_iostream_close (device->iostream);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to close the packet stream.");
|
||||
dc_status_set_error(&status, rc);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
|
||||
@ -302,7 +302,7 @@ oceans_s1_xmodem_packet (oceans_s1_device_t *device, unsigned char seq, unsigned
|
||||
}
|
||||
|
||||
unsigned short crc = array_uint16_be (packet + nbytes - 2);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (packet + 3, nbytes - 5, 0x0000);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (packet + 3, nbytes - 5, 0x0000, 0x0000);
|
||||
if (crc != ccrc) {
|
||||
ERROR (device->base.context, "Unexpected answer checksum (%04x %04x).", crc, ccrc);
|
||||
return DC_STATUS_PROTOCOL;
|
||||
|
||||
321
src/packet.c
Normal file
321
src/packet.c
Normal file
@ -0,0 +1,321 @@
|
||||
/*
|
||||
* libdivecomputer
|
||||
*
|
||||
* Copyright (C) 2023 Jef Driesen
|
||||
*
|
||||
* 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> // malloc, free
|
||||
#include <string.h>
|
||||
|
||||
#include "packet.h"
|
||||
|
||||
#include "iostream-private.h"
|
||||
#include "common-private.h"
|
||||
#include "context-private.h"
|
||||
|
||||
static dc_status_t dc_packet_set_timeout (dc_iostream_t *abstract, int timeout);
|
||||
static dc_status_t dc_packet_set_break (dc_iostream_t *abstract, unsigned int value);
|
||||
static dc_status_t dc_packet_set_dtr (dc_iostream_t *abstract, unsigned int value);
|
||||
static dc_status_t dc_packet_set_rts (dc_iostream_t *abstract, unsigned int value);
|
||||
static dc_status_t dc_packet_get_lines (dc_iostream_t *abstract, unsigned int *value);
|
||||
static dc_status_t dc_packet_get_available (dc_iostream_t *abstract, size_t *value);
|
||||
static dc_status_t dc_packet_configure (dc_iostream_t *abstract, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
|
||||
static dc_status_t dc_packet_poll (dc_iostream_t *abstract, int timeout);
|
||||
static dc_status_t dc_packet_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual);
|
||||
static dc_status_t dc_packet_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual);
|
||||
static dc_status_t dc_packet_ioctl (dc_iostream_t *abstract, unsigned int request, void *data, size_t size);
|
||||
static dc_status_t dc_packet_flush (dc_iostream_t *abstract);
|
||||
static dc_status_t dc_packet_purge (dc_iostream_t *abstract, dc_direction_t direction);
|
||||
static dc_status_t dc_packet_sleep (dc_iostream_t *abstract, unsigned int milliseconds);
|
||||
static dc_status_t dc_packet_close (dc_iostream_t *abstract);
|
||||
|
||||
typedef struct dc_packet_t {
|
||||
/* Base class. */
|
||||
dc_iostream_t base;
|
||||
/* Internal state. */
|
||||
dc_iostream_t *iostream;
|
||||
unsigned char *cache;
|
||||
size_t available;
|
||||
size_t offset;
|
||||
size_t isize;
|
||||
size_t osize;
|
||||
} dc_packet_t;
|
||||
|
||||
static const dc_iostream_vtable_t dc_packet_vtable = {
|
||||
sizeof(dc_packet_t),
|
||||
dc_packet_set_timeout, /* set_timeout */
|
||||
dc_packet_set_break, /* set_break */
|
||||
dc_packet_set_dtr, /* set_dtr */
|
||||
dc_packet_set_rts, /* set_rts */
|
||||
dc_packet_get_lines, /* get_lines */
|
||||
dc_packet_get_available, /* get_available */
|
||||
dc_packet_configure, /* configure */
|
||||
dc_packet_poll, /* poll */
|
||||
dc_packet_read, /* read */
|
||||
dc_packet_write, /* write */
|
||||
dc_packet_ioctl, /* ioctl */
|
||||
dc_packet_flush, /* flush */
|
||||
dc_packet_purge, /* purge */
|
||||
dc_packet_sleep, /* sleep */
|
||||
dc_packet_close, /* close */
|
||||
};
|
||||
|
||||
dc_status_t
|
||||
dc_packet_open (dc_iostream_t **out, dc_context_t *context, dc_iostream_t *base, size_t isize, size_t osize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_packet_t *packet = NULL;
|
||||
unsigned char *buffer = NULL;
|
||||
|
||||
if (out == NULL || base == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
packet = (dc_packet_t *) dc_iostream_allocate (NULL, &dc_packet_vtable, dc_iostream_get_transport(base));
|
||||
if (packet == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
status = DC_STATUS_NOMEMORY;
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
// Allocate the read buffer.
|
||||
if (isize) {
|
||||
buffer = (unsigned char *) malloc (isize);
|
||||
if (buffer == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
status = DC_STATUS_NOMEMORY;
|
||||
goto error_free;
|
||||
}
|
||||
}
|
||||
|
||||
packet->iostream = base;
|
||||
packet->cache = buffer;
|
||||
packet->available = 0;
|
||||
packet->offset = 0;
|
||||
packet->isize = isize;
|
||||
packet->osize = osize;
|
||||
|
||||
*out = (dc_iostream_t *) packet;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_free:
|
||||
dc_iostream_deallocate ((dc_iostream_t *) packet);
|
||||
error_exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_packet_set_timeout (dc_iostream_t *abstract, int timeout)
|
||||
{
|
||||
dc_packet_t *packet = (dc_packet_t *) abstract;
|
||||
|
||||
return dc_iostream_set_timeout (packet->iostream, timeout);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_packet_set_break (dc_iostream_t *abstract, unsigned int value)
|
||||
{
|
||||
dc_packet_t *packet = (dc_packet_t *) abstract;
|
||||
|
||||
return dc_iostream_set_break (packet->iostream, value);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_packet_set_dtr (dc_iostream_t *abstract, unsigned int value)
|
||||
{
|
||||
dc_packet_t *packet = (dc_packet_t *) abstract;
|
||||
|
||||
return dc_iostream_set_dtr (packet->iostream, value);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_packet_set_rts (dc_iostream_t *abstract, unsigned int value)
|
||||
{
|
||||
dc_packet_t *packet = (dc_packet_t *) abstract;
|
||||
|
||||
return dc_iostream_set_rts (packet->iostream, value);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_packet_get_lines (dc_iostream_t *abstract, unsigned int *value)
|
||||
{
|
||||
dc_packet_t *packet = (dc_packet_t *) abstract;
|
||||
|
||||
return dc_iostream_get_lines (packet->iostream, value);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_packet_get_available (dc_iostream_t *abstract, size_t *value)
|
||||
{
|
||||
dc_packet_t *packet = (dc_packet_t *) abstract;
|
||||
|
||||
if (packet->isize && packet->available) {
|
||||
if (value)
|
||||
*value = packet->available;
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return dc_iostream_get_available (packet->iostream, value);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_packet_configure (dc_iostream_t *abstract, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol)
|
||||
{
|
||||
dc_packet_t *packet = (dc_packet_t *) abstract;
|
||||
|
||||
return dc_iostream_configure (packet->iostream, baudrate, databits, parity, stopbits, flowcontrol);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_packet_poll (dc_iostream_t *abstract, int timeout)
|
||||
{
|
||||
dc_packet_t *packet = (dc_packet_t *) abstract;
|
||||
|
||||
if (packet->isize && packet->available)
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
return dc_iostream_poll (packet->iostream, timeout);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_packet_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_packet_t *packet = (dc_packet_t *) abstract;
|
||||
size_t nbytes = 0;
|
||||
|
||||
while (nbytes < size) {
|
||||
// Get the remaining size.
|
||||
size_t length = size - nbytes;
|
||||
|
||||
if (packet->isize) {
|
||||
if (packet->available == 0) {
|
||||
// Read a packet into the cache.
|
||||
size_t len = 0;
|
||||
status = dc_iostream_read (packet->iostream, packet->cache, packet->isize, &len);
|
||||
if (status != DC_STATUS_SUCCESS)
|
||||
break;
|
||||
|
||||
packet->available = len;
|
||||
packet->offset = 0;
|
||||
}
|
||||
|
||||
// Limit to the maximum packet size.
|
||||
if (length > packet->available)
|
||||
length = packet->available;
|
||||
|
||||
// Copy the data from the cached packet.
|
||||
memcpy ((unsigned char *) data + nbytes, packet->cache + packet->offset, length);
|
||||
packet->available -= length;
|
||||
packet->offset += length;
|
||||
} else {
|
||||
// Read the packet.
|
||||
status = dc_iostream_read (packet->iostream, (unsigned char *) data + nbytes, length, &length);
|
||||
if (status != DC_STATUS_SUCCESS)
|
||||
break;
|
||||
}
|
||||
|
||||
// Update the total number of bytes.
|
||||
nbytes += length;
|
||||
}
|
||||
|
||||
if (actual)
|
||||
*actual = nbytes;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_packet_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_packet_t *packet = (dc_packet_t *) abstract;
|
||||
size_t nbytes = 0;
|
||||
|
||||
while (nbytes < size) {
|
||||
// Get the remaining size.
|
||||
size_t length = size - nbytes;
|
||||
|
||||
// Limit to the maximum packet size.
|
||||
if (packet->osize) {
|
||||
if (length > packet->osize)
|
||||
length = packet->osize;
|
||||
}
|
||||
|
||||
// Write the packet.
|
||||
status = dc_iostream_write (packet->iostream, (const unsigned char *) data + nbytes, length, &length);
|
||||
if (status != DC_STATUS_SUCCESS)
|
||||
break;
|
||||
|
||||
// Update the total number of bytes.
|
||||
nbytes += length;
|
||||
}
|
||||
|
||||
if (actual)
|
||||
*actual = nbytes;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_packet_ioctl (dc_iostream_t *abstract, unsigned int request, void *data, size_t size)
|
||||
{
|
||||
dc_packet_t *packet = (dc_packet_t *) abstract;
|
||||
|
||||
return dc_iostream_ioctl (packet->iostream, request, data, size);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_packet_flush (dc_iostream_t *abstract)
|
||||
{
|
||||
dc_packet_t *packet = (dc_packet_t *) abstract;
|
||||
|
||||
return dc_iostream_flush (packet->iostream);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_packet_purge (dc_iostream_t *abstract, dc_direction_t direction)
|
||||
{
|
||||
dc_packet_t *packet = (dc_packet_t *) abstract;
|
||||
|
||||
if (direction & DC_DIRECTION_INPUT) {
|
||||
packet->available = 0;
|
||||
packet->offset = 0;
|
||||
}
|
||||
|
||||
return dc_iostream_purge (packet->iostream, direction);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_packet_sleep (dc_iostream_t *abstract, unsigned int milliseconds)
|
||||
{
|
||||
dc_packet_t *packet = (dc_packet_t *) abstract;
|
||||
|
||||
return dc_iostream_sleep (packet->iostream, milliseconds);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
dc_packet_close (dc_iostream_t *abstract)
|
||||
{
|
||||
dc_packet_t *packet = (dc_packet_t *) abstract;
|
||||
|
||||
free (packet->cache);
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
54
src/packet.h
Normal file
54
src/packet.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* libdivecomputer
|
||||
*
|
||||
* Copyright (C) 2023 Jef Driesen
|
||||
*
|
||||
* 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 DC_PACKET_H
|
||||
#define DC_PACKET_H
|
||||
|
||||
#include <libdivecomputer/common.h>
|
||||
#include <libdivecomputer/context.h>
|
||||
#include <libdivecomputer/iostream.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* Create a packet I/O stream layered on top of another base I/O stream.
|
||||
*
|
||||
* This layered I/O allows reading and writing a byte stream from the
|
||||
* underlying packet oriented transport. It changes the packet oriented
|
||||
* base transport into a stream oriented transport.
|
||||
*
|
||||
* @param[out] iostream A location to store the packet I/O stream.
|
||||
* @param[in] context A valid context.
|
||||
* @param[in] base A valid I/O stream.
|
||||
* @param[in] isize The input packet size in bytes.
|
||||
* @param[in] osize The output packet size in bytes.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_packet_open (dc_iostream_t **iostream, dc_context_t *context, dc_iostream_t *base, size_t isize, size_t osize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* DC_PACKET_H */
|
||||
@ -63,6 +63,7 @@
|
||||
#include "seac_screen.h"
|
||||
#include "deepblu_cosmiq.h"
|
||||
#include "oceans_s1.h"
|
||||
#include "divesoft_freedom.h"
|
||||
|
||||
// Not merged upstream yet
|
||||
#include "garmin.h"
|
||||
@ -202,6 +203,9 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t fa
|
||||
case DC_FAMILY_OCEANS_S1:
|
||||
rc = oceans_s1_parser_create (&parser, context);
|
||||
break;
|
||||
case DC_FAMILY_DIVESOFT_FREEDOM:
|
||||
rc = divesoft_freedom_parser_create (&parser, context);
|
||||
break;
|
||||
default:
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
|
||||
@ -177,7 +177,7 @@ reefnet_sensuspro_handshake (reefnet_sensuspro_device_t *device)
|
||||
|
||||
// Verify the checksum of the handshake packet.
|
||||
unsigned short crc = array_uint16_le (handshake + SZ_HANDSHAKE);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (handshake, SZ_HANDSHAKE, 0xffff);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (handshake, SZ_HANDSHAKE, 0xffff, 0x0000);
|
||||
if (crc != ccrc) {
|
||||
ERROR (abstract->context, "Unexpected answer checksum.");
|
||||
return DC_STATUS_PROTOCOL;
|
||||
@ -280,7 +280,7 @@ reefnet_sensuspro_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
}
|
||||
|
||||
unsigned short crc = array_uint16_le (answer + SZ_MEMORY);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (answer, SZ_MEMORY, 0xffff);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (answer, SZ_MEMORY, 0xffff, 0x0000);
|
||||
if (crc != ccrc) {
|
||||
ERROR (abstract->context, "Unexpected answer checksum.");
|
||||
return DC_STATUS_PROTOCOL;
|
||||
|
||||
@ -224,7 +224,7 @@ reefnet_sensusultra_packet (reefnet_sensusultra_device_t *device, unsigned char
|
||||
|
||||
// Verify the checksum of the packet.
|
||||
unsigned short crc = array_uint16_le (data + size - 2);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (data + header, size - header - 2, 0xffff);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (data + header, size - header - 2, 0xffff, 0x0000);
|
||||
if (crc != ccrc) {
|
||||
ERROR (abstract->context, "Unexpected answer checksum.");
|
||||
return DC_STATUS_PROTOCOL;
|
||||
@ -477,7 +477,7 @@ reefnet_sensusultra_device_write_user (dc_device_t *abstract, const unsigned cha
|
||||
}
|
||||
|
||||
// Send the checksum to the device.
|
||||
unsigned short crc = checksum_crc16_ccitt (data, SZ_USER, 0xffff);
|
||||
unsigned short crc = checksum_crc16_ccitt (data, SZ_USER, 0xffff, 0x0000);
|
||||
rc = reefnet_sensusultra_send_ushort (device, crc);
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
@ -115,7 +115,7 @@ seac_screen_send (seac_screen_device_t *device, unsigned short cmd, const unsign
|
||||
if (size) {
|
||||
memcpy (packet + 5, data, size);
|
||||
}
|
||||
crc = checksum_crc16_ccitt (packet, size + 5, 0xFFFF);
|
||||
crc = checksum_crc16_ccitt (packet, size + 5, 0xFFFF, 0x0000);
|
||||
packet[size + 5] = (crc >> 8) & 0xFF;
|
||||
packet[size + 6] = (crc ) & 0xFF;
|
||||
|
||||
@ -165,7 +165,7 @@ seac_screen_receive (seac_screen_device_t *device, unsigned short cmd, unsigned
|
||||
|
||||
// Verify the checksum.
|
||||
unsigned short crc = array_uint16_be (packet + 1 + length - 2);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (packet, 1 + length - 2, 0xFFFF);
|
||||
unsigned short ccrc = checksum_crc16_ccitt (packet, 1 + length - 2, 0xFFFF, 0x0000);
|
||||
if (crc != ccrc) {
|
||||
ERROR (abstract->context, "Unexpected packet checksum (%04x %04x).", crc, ccrc);
|
||||
return DC_STATUS_PROTOCOL;
|
||||
@ -486,8 +486,8 @@ seac_screen_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback,
|
||||
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
|
||||
|
||||
// Check the header checksums.
|
||||
if (checksum_crc16_ccitt (logbook[i].header, SZ_HEADER / 2, 0xFFFF) != 0 ||
|
||||
checksum_crc16_ccitt (logbook[i].header + SZ_HEADER / 2, SZ_HEADER / 2, 0xFFFF) != 0) {
|
||||
if (checksum_crc16_ccitt (logbook[i].header, SZ_HEADER / 2, 0xFFFF, 0x0000) != 0 ||
|
||||
checksum_crc16_ccitt (logbook[i].header + SZ_HEADER / 2, SZ_HEADER / 2, 0xFFFF, 0x0000) != 0) {
|
||||
ERROR (abstract->context, "Unexpected header checksum.");
|
||||
status = DC_STATUS_DATAFORMAT;
|
||||
goto error_free_logbook;
|
||||
|
||||
@ -283,8 +283,8 @@ seac_screen_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
if (abstract->size < SZ_HEADER)
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
|
||||
if (checksum_crc16_ccitt (data, SZ_HEADER / 2, 0xFFFF) != 0 ||
|
||||
checksum_crc16_ccitt (data + SZ_HEADER / 2, SZ_HEADER / 2, 0xFFFF) != 0) {
|
||||
if (checksum_crc16_ccitt (data, SZ_HEADER / 2, 0xFFFF, 0x0000) != 0 ||
|
||||
checksum_crc16_ccitt (data + SZ_HEADER / 2, SZ_HEADER / 2, 0xFFFF, 0x0000) != 0) {
|
||||
ERROR (abstract->context, "Unexpected header checksum.");
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
@ -303,7 +303,7 @@ seac_screen_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
while (offset + SZ_SAMPLE <= size) {
|
||||
dc_sample_value_t sample = {0};
|
||||
|
||||
if (checksum_crc16_ccitt (data + offset, SZ_SAMPLE, 0xFFFF) != 0) {
|
||||
if (checksum_crc16_ccitt (data + offset, SZ_SAMPLE, 0xFFFF, 0x0000) != 0) {
|
||||
ERROR (abstract->context, "Unexpected sample checksum.");
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include "array.h"
|
||||
#include "platform.h"
|
||||
#include "checksum.h"
|
||||
#include "hdlc.h"
|
||||
|
||||
#define EONSTEEL 0
|
||||
#define EONCORE 1
|
||||
@ -80,14 +81,10 @@ struct directory_entry {
|
||||
#define MAXDATA_SIZE 2048
|
||||
#define CRC_SIZE 4
|
||||
|
||||
// HDLC special characters
|
||||
#define END 0x7E
|
||||
#define ESC 0x7D
|
||||
#define ESC_BIT 0x20
|
||||
|
||||
static dc_status_t suunto_eonsteel_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
|
||||
static dc_status_t suunto_eonsteel_device_foreach(dc_device_t *abstract, dc_dive_callback_t callback, void *userdata);
|
||||
static dc_status_t suunto_eonsteel_device_timesync(dc_device_t *abstract, const dc_datetime_t *datetime);
|
||||
static dc_status_t suunto_eonsteel_device_close (dc_device_t *abstract);
|
||||
|
||||
static const dc_device_vtable_t suunto_eonsteel_device_vtable = {
|
||||
sizeof(suunto_eonsteel_device_t),
|
||||
@ -98,7 +95,7 @@ static const dc_device_vtable_t suunto_eonsteel_device_vtable = {
|
||||
NULL, /* dump */
|
||||
suunto_eonsteel_device_foreach, /* foreach */
|
||||
suunto_eonsteel_device_timesync, /* timesync */
|
||||
NULL /* close */
|
||||
suunto_eonsteel_device_close /* close */
|
||||
};
|
||||
|
||||
static const char dive_directory[] = "0:/dives";
|
||||
@ -127,156 +124,6 @@ static struct directory_entry *alloc_dirent(int type, int len, const char *name)
|
||||
return res;
|
||||
}
|
||||
|
||||
static void put_le16(unsigned short val, unsigned char *p)
|
||||
{
|
||||
p[0] = val;
|
||||
p[1] = val >> 8;
|
||||
}
|
||||
|
||||
static void put_le32(unsigned int val, unsigned char *p)
|
||||
{
|
||||
p[0] = val;
|
||||
p[1] = val >> 8;
|
||||
p[2] = val >> 16;
|
||||
p[3] = val >> 24;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
suunto_eonsteel_hdlc_write (suunto_eonsteel_device_t *device, const unsigned char data[], size_t size, size_t *actual)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
unsigned char buffer[20];
|
||||
size_t nbytes = 0;
|
||||
|
||||
// Start of the packet.
|
||||
buffer[nbytes++] = END;
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
unsigned char c = data[i];
|
||||
|
||||
if (c == END || c == ESC) {
|
||||
// Append the escape character.
|
||||
buffer[nbytes++] = ESC;
|
||||
|
||||
// Flush the buffer if necessary.
|
||||
if (nbytes >= sizeof(buffer)) {
|
||||
status = dc_iostream_write(device->iostream, buffer, nbytes, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR(device->base.context, "Failed to send the packet.");
|
||||
return status;
|
||||
}
|
||||
|
||||
nbytes = 0;
|
||||
}
|
||||
|
||||
// Escape the character.
|
||||
c ^= ESC_BIT;
|
||||
}
|
||||
|
||||
// Append the character.
|
||||
buffer[nbytes++] = c;
|
||||
|
||||
// Flush the buffer if necessary.
|
||||
if (nbytes >= sizeof(buffer)) {
|
||||
status = dc_iostream_write(device->iostream, buffer, nbytes, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR(device->base.context, "Failed to send the packet.");
|
||||
return status;
|
||||
}
|
||||
|
||||
nbytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// End of the packet.
|
||||
buffer[nbytes++] = END;
|
||||
|
||||
// Flush the buffer.
|
||||
status = dc_iostream_write(device->iostream, buffer, nbytes, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR(device->base.context, "Failed to send the packet.");
|
||||
return status;
|
||||
}
|
||||
|
||||
if (actual)
|
||||
*actual = size;
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
suunto_eonsteel_hdlc_read (suunto_eonsteel_device_t *device, unsigned char data[], size_t size, size_t *actual)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
unsigned char buffer[20];
|
||||
unsigned int initialized = 0;
|
||||
unsigned int escaped = 0;
|
||||
size_t nbytes = 0;
|
||||
|
||||
while (1) {
|
||||
// Read a single data packet.
|
||||
size_t transferred = 0;
|
||||
status = dc_iostream_read(device->iostream, buffer, sizeof(buffer), &transferred);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR(device->base.context, "Failed to receive the packet.");
|
||||
return status;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < transferred; ++i) {
|
||||
unsigned char c = buffer[i];
|
||||
|
||||
if (c == END) {
|
||||
if (escaped) {
|
||||
ERROR (device->base.context, "HDLC frame escaped the special character %02x.", c);
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
|
||||
if (initialized) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
initialized = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!initialized) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == ESC) {
|
||||
if (escaped) {
|
||||
ERROR (device->base.context, "HDLC frame escaped the special character %02x.", c);
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
escaped = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (escaped) {
|
||||
c ^= ESC_BIT;
|
||||
escaped = 0;
|
||||
}
|
||||
|
||||
if (nbytes < size)
|
||||
data[nbytes] = c;
|
||||
nbytes++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (nbytes > size) {
|
||||
ERROR(device->base.context, "Insufficient buffer space available.");
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
|
||||
if (actual)
|
||||
*actual = nbytes;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a single 64-byte packet from the dive computer. This handles packet
|
||||
* logging and any obvious packet-level errors, and returns the payload of
|
||||
@ -338,7 +185,7 @@ suunto_eonsteel_receive_ble(suunto_eonsteel_device_t *device, unsigned char data
|
||||
unsigned char buffer[HEADER_SIZE + MAXDATA_SIZE + CRC_SIZE];
|
||||
size_t transferred = 0;
|
||||
|
||||
rc = suunto_eonsteel_hdlc_read(device, buffer, sizeof(buffer), &transferred);
|
||||
rc = dc_iostream_read(device->iostream, buffer, sizeof(buffer), &transferred);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR(device->base.context, "Failed to receive the packet.");
|
||||
return rc;
|
||||
@ -352,7 +199,7 @@ suunto_eonsteel_receive_ble(suunto_eonsteel_device_t *device, unsigned char data
|
||||
unsigned int nbytes = transferred - CRC_SIZE;
|
||||
|
||||
unsigned int crc = array_uint32_le(buffer + nbytes);
|
||||
unsigned int ccrc = checksum_crc32(buffer, nbytes);
|
||||
unsigned int ccrc = checksum_crc32r(buffer, nbytes);
|
||||
if (crc != ccrc) {
|
||||
ERROR(device->base.context, "Invalid checksum (expected %08x, received %08x).", ccrc, crc);
|
||||
return DC_STATUS_PROTOCOL;
|
||||
@ -394,16 +241,16 @@ suunto_eonsteel_send(suunto_eonsteel_device_t *device,
|
||||
buf[1] = size + HEADER_SIZE;
|
||||
|
||||
// 2-byte LE command word
|
||||
put_le16(cmd, buf + 2);
|
||||
array_uint16_le_set(buf + 2, cmd);
|
||||
|
||||
// 4-byte LE magic value (starts at 1)
|
||||
put_le32(device->magic, buf + 4);
|
||||
array_uint32_le_set(buf + 4, device->magic);
|
||||
|
||||
// 2-byte LE sequence number;
|
||||
put_le16(device->seq, buf + 8);
|
||||
array_uint16_le_set(buf + 8, device->seq);
|
||||
|
||||
// 4-byte LE length
|
||||
put_le32(size, buf + 10);
|
||||
array_uint32_le_set(buf + 10, size);
|
||||
|
||||
// .. followed by actual data
|
||||
if (size) {
|
||||
@ -411,11 +258,11 @@ suunto_eonsteel_send(suunto_eonsteel_device_t *device,
|
||||
}
|
||||
|
||||
// 4 byte LE checksum
|
||||
unsigned int crc = checksum_crc32(buf + 2, size + HEADER_SIZE);
|
||||
put_le32(crc, buf + 14 + size);
|
||||
unsigned int crc = checksum_crc32r(buf + 2, size + HEADER_SIZE);
|
||||
array_uint32_le_set(buf + 14 + size, crc);
|
||||
|
||||
if (dc_iostream_get_transport(device->iostream) == DC_TRANSPORT_BLE) {
|
||||
rc = suunto_eonsteel_hdlc_write(device, buf + 2, size + HEADER_SIZE + CRC_SIZE, NULL);
|
||||
rc = dc_iostream_write(device->iostream, buf + 2, size + HEADER_SIZE + CRC_SIZE, NULL);
|
||||
} else {
|
||||
rc = dc_iostream_write(device->iostream, buf, sizeof(buf) - CRC_SIZE, NULL);
|
||||
}
|
||||
@ -591,8 +438,8 @@ read_file(suunto_eonsteel_device_t *eon, const char *filename, dc_buffer_t *buf)
|
||||
ask = size;
|
||||
if (ask > 1024)
|
||||
ask = 1024;
|
||||
put_le32(1234, cmdbuf+0); // Not file offset, after all
|
||||
put_le32(ask, cmdbuf+4); // Size of read
|
||||
array_uint32_le_set(cmdbuf + 0, 1234); // Not file offset, after all
|
||||
array_uint32_le_set(cmdbuf + 4, ask); // Size of read
|
||||
rc = suunto_eonsteel_transfer(eon, CMD_FILE_READ,
|
||||
cmdbuf, 8, result, sizeof(result), &n);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
@ -705,7 +552,7 @@ get_file_list(suunto_eonsteel_device_t *eon, struct directory_entry **res)
|
||||
unsigned int n = 0;
|
||||
unsigned int cmdlen;
|
||||
|
||||
put_le32(0, cmd);
|
||||
array_uint32_le_set(cmd, 0);
|
||||
memcpy(cmd + 4, dive_directory, sizeof(dive_directory));
|
||||
cmdlen = 4 + sizeof(dive_directory);
|
||||
rc = suunto_eonsteel_transfer(eon, CMD_DIR_OPEN,
|
||||
@ -771,6 +618,7 @@ suunto_eonsteel_device_open(dc_device_t **out, dc_context_t *context, dc_iostrea
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
suunto_eonsteel_device_t *eon = NULL;
|
||||
dc_transport_t transport = dc_iostream_get_transport (iostream);
|
||||
|
||||
if (out == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
@ -780,17 +628,26 @@ suunto_eonsteel_device_open(dc_device_t **out, dc_context_t *context, dc_iostrea
|
||||
return DC_STATUS_NOMEMORY;
|
||||
|
||||
// Set up the magic handshake fields
|
||||
eon->iostream = iostream;
|
||||
eon->model = model;
|
||||
eon->magic = INIT_MAGIC;
|
||||
eon->seq = INIT_SEQ;
|
||||
memset (eon->version, 0, sizeof (eon->version));
|
||||
memset (eon->fingerprint, 0, sizeof (eon->fingerprint));
|
||||
|
||||
if (transport == DC_TRANSPORT_BLE) {
|
||||
status = dc_hdlc_open (&eon->iostream, context, iostream, 20, 20);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to create the HDLC stream.");
|
||||
goto error_free;
|
||||
}
|
||||
} else {
|
||||
eon->iostream = iostream;
|
||||
}
|
||||
|
||||
status = dc_iostream_set_timeout(eon->iostream, 5000);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (context, "Failed to set the timeout.");
|
||||
goto error_free;
|
||||
goto error_free_iostream;
|
||||
}
|
||||
|
||||
const unsigned char init[] = {0x02, 0x00, 0x2a, 0x00};
|
||||
@ -798,18 +655,34 @@ suunto_eonsteel_device_open(dc_device_t **out, dc_context_t *context, dc_iostrea
|
||||
init, sizeof(init), eon->version, sizeof(eon->version), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR(context, "unable to initialize device");
|
||||
goto error_free;
|
||||
goto error_free_iostream;
|
||||
}
|
||||
|
||||
*out = (dc_device_t *) eon;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_free_iostream:
|
||||
if (transport == DC_TRANSPORT_BLE) {
|
||||
dc_iostream_close (eon->iostream);
|
||||
}
|
||||
error_free:
|
||||
free(eon);
|
||||
dc_device_deallocate ((dc_device_t *) eon);
|
||||
return status;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
suunto_eonsteel_device_close (dc_device_t *abstract)
|
||||
{
|
||||
suunto_eonsteel_device_t *device = (suunto_eonsteel_device_t *) abstract;
|
||||
|
||||
if (dc_iostream_get_transport (device->iostream) == DC_TRANSPORT_BLE) {
|
||||
return dc_iostream_close (device->iostream);
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
suunto_eonsteel_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size)
|
||||
{
|
||||
@ -890,7 +763,7 @@ suunto_eonsteel_device_foreach(dc_device_t *abstract, dc_dive_callback_t callbac
|
||||
break;
|
||||
}
|
||||
|
||||
put_le32(time, buf);
|
||||
array_uint32_le_set(buf, time);
|
||||
|
||||
if (memcmp (buf, eon->fingerprint, sizeof (eon->fingerprint)) == 0) {
|
||||
skip = 1;
|
||||
|
||||
@ -893,25 +893,6 @@ uwatec_galileo_identify (unsigned char value)
|
||||
}
|
||||
|
||||
|
||||
static unsigned int
|
||||
uwatec_smart_fixsignbit (unsigned int x, unsigned int n)
|
||||
{
|
||||
if (n <= 0 || n > 32)
|
||||
return 0;
|
||||
|
||||
unsigned int signbit = (1 << (n - 1));
|
||||
unsigned int mask = (signbit - 1);
|
||||
|
||||
// When turning a two's-complement number with a certain number
|
||||
// of bits into one with more bits, the sign bit must be repeated
|
||||
// in all the extra bits.
|
||||
if ((x & signbit) == signbit)
|
||||
return x | ~mask;
|
||||
else
|
||||
return x & mask;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t callback, void *userdata)
|
||||
{
|
||||
@ -1018,7 +999,7 @@ uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t callback
|
||||
}
|
||||
|
||||
// Fix the sign bit.
|
||||
signed int svalue = uwatec_smart_fixsignbit (value, nbits);
|
||||
signed int svalue = signextend (value, nbits);
|
||||
|
||||
// Parse the value.
|
||||
unsigned int idx = 0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user