Compare commits
2 Commits
master
...
release-0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb987642e3 | ||
|
|
baa6944697 |
22
.github/workflows/build.yml
vendored
22
.github/workflows/build.yml
vendored
@ -19,7 +19,7 @@ jobs:
|
|||||||
CC: ${{ matrix.compiler }}
|
CC: ${{ matrix.compiler }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: sudo apt-get install libbluetooth-dev libusb-1.0-0-dev
|
run: sudo apt-get install libbluetooth-dev libusb-1.0-0-dev
|
||||||
- run: autoreconf --install --force
|
- run: autoreconf --install --force
|
||||||
@ -30,7 +30,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
make install DESTDIR=$PWD/artifacts
|
make install DESTDIR=$PWD/artifacts
|
||||||
tar -czf ${{ github.job }}-${{ matrix.compiler }}.tar.gz -C artifacts usr
|
tar -czf ${{ github.job }}-${{ matrix.compiler }}.tar.gz -C artifacts usr
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ${{ github.job }}-${{ matrix.compiler }}
|
name: ${{ github.job }}-${{ matrix.compiler }}
|
||||||
path: ${{ github.job }}-${{ matrix.compiler }}.tar.gz
|
path: ${{ github.job }}-${{ matrix.compiler }}.tar.gz
|
||||||
@ -50,7 +50,7 @@ jobs:
|
|||||||
CC: ${{ matrix.compiler }}
|
CC: ${{ matrix.compiler }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: brew install autoconf automake libtool hidapi libusb
|
run: brew install autoconf automake libtool hidapi libusb
|
||||||
- run: autoreconf --install --force
|
- run: autoreconf --install --force
|
||||||
@ -61,7 +61,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
make install DESTDIR=$PWD/artifacts
|
make install DESTDIR=$PWD/artifacts
|
||||||
tar -czf ${{ github.job }}-${{ matrix.compiler }}.tar.gz -C artifacts usr
|
tar -czf ${{ github.job }}-${{ matrix.compiler }}.tar.gz -C artifacts usr
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ${{ github.job }}-${{ matrix.compiler }}
|
name: ${{ github.job }}-${{ matrix.compiler }}
|
||||||
path: ${{ github.job }}-${{ matrix.compiler }}.tar.gz
|
path: ${{ github.job }}-${{ matrix.compiler }}.tar.gz
|
||||||
@ -78,7 +78,7 @@ jobs:
|
|||||||
arch: [i686, x86_64]
|
arch: [i686, x86_64]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: sudo apt-get install gcc-mingw-w64 binutils-mingw-w64 mingw-w64-tools
|
run: sudo apt-get install gcc-mingw-w64 binutils-mingw-w64 mingw-w64-tools
|
||||||
- name: Install libusb
|
- name: Install libusb
|
||||||
@ -118,7 +118,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
make install DESTDIR=$PWD/artifacts
|
make install DESTDIR=$PWD/artifacts
|
||||||
tar -czf ${{ github.job }}-${{ matrix.arch }}.tar.gz -C artifacts usr
|
tar -czf ${{ github.job }}-${{ matrix.arch }}.tar.gz -C artifacts usr
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ${{ github.job }}-${{ matrix.arch }}
|
name: ${{ github.job }}-${{ matrix.arch }}
|
||||||
path: ${{ github.job }}-${{ matrix.arch }}.tar.gz
|
path: ${{ github.job }}-${{ matrix.arch }}.tar.gz
|
||||||
@ -138,7 +138,7 @@ jobs:
|
|||||||
CONFIGURATION: Release
|
CONFIGURATION: Release
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
- uses: msys2/setup-msys2@v2
|
- uses: msys2/setup-msys2@v2
|
||||||
with:
|
with:
|
||||||
install: autoconf automake libtool pkg-config make gcc
|
install: autoconf automake libtool pkg-config make gcc
|
||||||
@ -147,9 +147,9 @@ jobs:
|
|||||||
./configure --prefix=/usr
|
./configure --prefix=/usr
|
||||||
make -C src revision.h
|
make -C src revision.h
|
||||||
shell: msys2 {0}
|
shell: msys2 {0}
|
||||||
- uses: microsoft/setup-msbuild@v2
|
- uses: microsoft/setup-msbuild@v1
|
||||||
- run: msbuild -m -p:Platform=${{ matrix.platform }} -p:Configuration=${{ env.CONFIGURATION }} contrib/msvc/libdivecomputer.vcxproj
|
- run: msbuild -m -p:Platform=${{ matrix.platform }} -p:Configuration=${{ env.CONFIGURATION }} contrib/msvc/libdivecomputer.vcxproj
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ${{ github.job }}-${{ matrix.platform }}
|
name: ${{ github.job }}-${{ matrix.platform }}
|
||||||
path: contrib/msvc/${{ matrix.platform }}/${{ env.CONFIGURATION }}/bin
|
path: contrib/msvc/${{ matrix.platform }}/${{ env.CONFIGURATION }}/bin
|
||||||
@ -161,13 +161,13 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
- run: |
|
- run: |
|
||||||
autoreconf --install --force
|
autoreconf --install --force
|
||||||
./configure --prefix=/usr
|
./configure --prefix=/usr
|
||||||
make -C src revision.h
|
make -C src revision.h
|
||||||
- run: $ANDROID_NDK/ndk-build -C contrib/android NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk
|
- run: $ANDROID_NDK/ndk-build -C contrib/android NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ${{ github.job }}
|
name: ${{ github.job }}
|
||||||
path: contrib/android/libs
|
path: contrib/android/libs
|
||||||
|
|||||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
|||||||
name: Release
|
name: Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Version number
|
- name: Version number
|
||||||
id: version
|
id: version
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# Versioning.
|
# Versioning.
|
||||||
m4_define([dc_version_major],[0])
|
m4_define([dc_version_major],[0])
|
||||||
m4_define([dc_version_minor],[9])
|
m4_define([dc_version_minor],[8])
|
||||||
m4_define([dc_version_micro],[0])
|
m4_define([dc_version_micro],[1])
|
||||||
m4_define([dc_version_suffix],[devel])
|
m4_define([dc_version_suffix],[devel])
|
||||||
m4_define([dc_version],dc_version_major.dc_version_minor.dc_version_micro[]m4_ifset([dc_version_suffix],-[dc_version_suffix]))
|
m4_define([dc_version],dc_version_major.dc_version_minor.dc_version_micro[]m4_ifset([dc_version_suffix],-[dc_version_suffix]))
|
||||||
|
|
||||||
|
|||||||
@ -71,7 +71,6 @@ LOCAL_SRC_FILES := \
|
|||||||
src/oceans_s1_parser.c \
|
src/oceans_s1_parser.c \
|
||||||
src/packet.c \
|
src/packet.c \
|
||||||
src/parser.c \
|
src/parser.c \
|
||||||
src/pelagic_i330r.c \
|
|
||||||
src/platform.c \
|
src/platform.c \
|
||||||
src/rbstream.c \
|
src/rbstream.c \
|
||||||
src/reefnet_sensus.c \
|
src/reefnet_sensus.c \
|
||||||
|
|||||||
@ -239,7 +239,6 @@
|
|||||||
<ClCompile Include="..\..\src\oceans_s1_parser.c" />
|
<ClCompile Include="..\..\src\oceans_s1_parser.c" />
|
||||||
<ClCompile Include="..\..\src\packet.c" />
|
<ClCompile Include="..\..\src\packet.c" />
|
||||||
<ClCompile Include="..\..\src\parser.c" />
|
<ClCompile Include="..\..\src\parser.c" />
|
||||||
<ClCompile Include="..\..\src\pelagic_i330r.c" />
|
|
||||||
<ClCompile Include="..\..\src\platform.c" />
|
<ClCompile Include="..\..\src\platform.c" />
|
||||||
<ClCompile Include="..\..\src\rbstream.c" />
|
<ClCompile Include="..\..\src\rbstream.c" />
|
||||||
<ClCompile Include="..\..\src\reefnet_sensus.c" />
|
<ClCompile Include="..\..\src\reefnet_sensus.c" />
|
||||||
@ -332,6 +331,7 @@
|
|||||||
<ClInclude Include="..\..\src\cressi_leonardo.h" />
|
<ClInclude Include="..\..\src\cressi_leonardo.h" />
|
||||||
<ClInclude Include="..\..\src\deepblu_cosmiq.h" />
|
<ClInclude Include="..\..\src\deepblu_cosmiq.h" />
|
||||||
<ClInclude Include="..\..\src\deepsix_excursion.h" />
|
<ClInclude Include="..\..\src\deepsix_excursion.h" />
|
||||||
|
<ClInclude Include="..\..\src\descriptor-private.h" />
|
||||||
<ClInclude Include="..\..\src\device-private.h" />
|
<ClInclude Include="..\..\src\device-private.h" />
|
||||||
<ClInclude Include="..\..\src\diverite_nitekq.h" />
|
<ClInclude Include="..\..\src\diverite_nitekq.h" />
|
||||||
<ClInclude Include="..\..\src\divesoft_freedom.h" />
|
<ClInclude Include="..\..\src\divesoft_freedom.h" />
|
||||||
@ -358,7 +358,6 @@
|
|||||||
<ClInclude Include="..\..\src\oceans_s1_common.h" />
|
<ClInclude Include="..\..\src\oceans_s1_common.h" />
|
||||||
<ClInclude Include="..\..\src\packet.h" />
|
<ClInclude Include="..\..\src\packet.h" />
|
||||||
<ClInclude Include="..\..\src\parser-private.h" />
|
<ClInclude Include="..\..\src\parser-private.h" />
|
||||||
<ClInclude Include="..\..\src\pelagic_i330r.h" />
|
|
||||||
<ClInclude Include="..\..\src\platform.h" />
|
<ClInclude Include="..\..\src\platform.h" />
|
||||||
<ClInclude Include="..\..\src\rbstream.h" />
|
<ClInclude Include="..\..\src\rbstream.h" />
|
||||||
<ClInclude Include="..\..\src\reefnet_sensus.h" />
|
<ClInclude Include="..\..\src\reefnet_sensus.h" />
|
||||||
|
|||||||
@ -32,6 +32,7 @@ MANPAGES = \
|
|||||||
dc_parser_get_field.3 \
|
dc_parser_get_field.3 \
|
||||||
dc_parser_new.3 \
|
dc_parser_new.3 \
|
||||||
dc_parser_samples_foreach.3 \
|
dc_parser_samples_foreach.3 \
|
||||||
|
dc_parser_set_data.3 \
|
||||||
dc_bluetooth_open.3 \
|
dc_bluetooth_open.3 \
|
||||||
dc_bluetooth_iterator_new.3 \
|
dc_bluetooth_iterator_new.3 \
|
||||||
dc_bluetooth_device_get_address.3 \
|
dc_bluetooth_device_get_address.3 \
|
||||||
|
|||||||
@ -53,7 +53,7 @@ with
|
|||||||
Each dive invokes
|
Each dive invokes
|
||||||
.Fa callback
|
.Fa callback
|
||||||
with the dive data, which should be parsed with
|
with the dive data, which should be parsed with
|
||||||
.Xr dc_parser_new 3 ,
|
.Xr dc_parser_set_data 3 ,
|
||||||
and the binary fingerprint of the dive.
|
and the binary fingerprint of the dive.
|
||||||
The fingerprint can be used to record the newest dive and stop
|
The fingerprint can be used to record the newest dive and stop
|
||||||
processing (on subsequent invocations) when the same dive fingerprint is
|
processing (on subsequent invocations) when the same dive fingerprint is
|
||||||
@ -72,7 +72,7 @@ If
|
|||||||
returns zero, this will not be reflected in the return value (usually
|
returns zero, this will not be reflected in the return value (usually
|
||||||
.Dv DC_STATUS_SUCCESS ) .
|
.Dv DC_STATUS_SUCCESS ) .
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr dc_parser_new 3
|
.Xr dc_parser_set_data 3
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
The
|
The
|
||||||
.Lb libdivecomputer
|
.Lb libdivecomputer
|
||||||
|
|||||||
@ -37,7 +37,7 @@
|
|||||||
Extract the date and time of a dive,
|
Extract the date and time of a dive,
|
||||||
.Fa parser ,
|
.Fa parser ,
|
||||||
previously initialised with
|
previously initialised with
|
||||||
.Xr dc_parser_new 3 .
|
.Xr dc_parser_set_data 3 .
|
||||||
This returns the broken-down time-stamp of the dive in the local time of
|
This returns the broken-down time-stamp of the dive in the local time of
|
||||||
the dive.
|
the dive.
|
||||||
.Pp
|
.Pp
|
||||||
@ -57,7 +57,7 @@ messages on further failure.
|
|||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr dc_datetime_gmtime 3 ,
|
.Xr dc_datetime_gmtime 3 ,
|
||||||
.Xr dc_datetime_localtime 3 ,
|
.Xr dc_datetime_localtime 3 ,
|
||||||
.Xr dc_parser_new 3
|
.Xr dc_parser_set_data 3
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
The
|
The
|
||||||
.Lb libdivecomputer
|
.Lb libdivecomputer
|
||||||
|
|||||||
@ -39,7 +39,7 @@
|
|||||||
Extract a field from a dive,
|
Extract a field from a dive,
|
||||||
.Fa parser ,
|
.Fa parser ,
|
||||||
previously initialised with
|
previously initialised with
|
||||||
.Xr dc_parser_new 3 .
|
.Xr dc_parser_set_data 3 .
|
||||||
The
|
The
|
||||||
.Fa value
|
.Fa value
|
||||||
field type depends upon the
|
field type depends upon the
|
||||||
@ -187,7 +187,7 @@ if the field was retrieved,
|
|||||||
if the field is not supported by the device, or other error messages on
|
if the field is not supported by the device, or other error messages on
|
||||||
further failure.
|
further failure.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr dc_parser_new 3
|
.Xr dc_parser_set_data 3
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
The
|
The
|
||||||
.Lb libdivecomputer
|
.Lb libdivecomputer
|
||||||
|
|||||||
@ -39,6 +39,8 @@
|
|||||||
.Fa "dc_parser_t **parser"
|
.Fa "dc_parser_t **parser"
|
||||||
.Fa "dc_context_t *context"
|
.Fa "dc_context_t *context"
|
||||||
.Fa "dc_descriptor_t *descriptor"
|
.Fa "dc_descriptor_t *descriptor"
|
||||||
|
.Fa "unsigned int devtime"
|
||||||
|
.Fa "dc_ticks_t systime"
|
||||||
.Fc
|
.Fc
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
Creates a parser for a single dive extracted from the dive computer with
|
Creates a parser for a single dive extracted from the dive computer with
|
||||||
@ -53,6 +55,10 @@ parameter; and
|
|||||||
.Nm dc_parser_new2 ,
|
.Nm dc_parser_new2 ,
|
||||||
which is given device values (model, etc.) directly.
|
which is given device values (model, etc.) directly.
|
||||||
.Pp
|
.Pp
|
||||||
|
After filling in the
|
||||||
|
.Fa parser
|
||||||
|
parameter, one usually sets parser data with
|
||||||
|
.Xr dc_parser_set_data 3 .
|
||||||
The pointer must later be freed with
|
The pointer must later be freed with
|
||||||
.Xr dc_parser_destroy 3 .
|
.Xr dc_parser_destroy 3 .
|
||||||
.Sh RETURN VALUES
|
.Sh RETURN VALUES
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
.Ft "typedef void"
|
.Ft "typedef void"
|
||||||
.Fo "(*dc_sample_callback_t)"
|
.Fo "(*dc_sample_callback_t)"
|
||||||
.Fa "dc_sample_type_t type"
|
.Fa "dc_sample_type_t type"
|
||||||
.Fa "const dc_sample_value_t *value"
|
.Fa "dc_sample_value_t value"
|
||||||
.Fa "void *userdata"
|
.Fa "void *userdata"
|
||||||
.Fc
|
.Fc
|
||||||
.Ft dc_status_t
|
.Ft dc_status_t
|
||||||
@ -42,7 +42,7 @@
|
|||||||
.Fc
|
.Fc
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
Extract the samples taken during a dive as previously initialised with
|
Extract the samples taken during a dive as previously initialised with
|
||||||
.Xr dc_parser_new 3 .
|
.Xr dc_parser_set_data 3 .
|
||||||
Each sample is passed to
|
Each sample is passed to
|
||||||
.Fa callback
|
.Fa callback
|
||||||
with the
|
with the
|
||||||
@ -63,7 +63,7 @@ closed.
|
|||||||
The following sample types may be raised:
|
The following sample types may be raised:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
.It Dv DC_SAMPLE_TIME
|
.It Dv DC_SAMPLE_TIME
|
||||||
The time of the sample taken in milliseconds after the dive began.
|
The time of the sample taken in seconds after the dive began.
|
||||||
Set in the
|
Set in the
|
||||||
.Fa time
|
.Fa time
|
||||||
field.
|
field.
|
||||||
@ -184,7 +184,7 @@ Returns
|
|||||||
.Dv DC_STATUS_OK
|
.Dv DC_STATUS_OK
|
||||||
on success and another code on failure.
|
on success and another code on failure.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr dc_parser_new 3
|
.Xr dc_parser_set_data 3
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
The
|
The
|
||||||
.Lb libdivecomputer
|
.Lb libdivecomputer
|
||||||
|
|||||||
65
doc/man/dc_parser_set_data.3
Normal file
65
doc/man/dc_parser_set_data.3
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
.\"
|
||||||
|
.\" libdivecomputer
|
||||||
|
.\"
|
||||||
|
.\" Copyright (C) 2017 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||||
|
.\"
|
||||||
|
.\" 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
|
||||||
|
.\"
|
||||||
|
.Dd January 5, 2017
|
||||||
|
.Dt DC_PARSER_SET_DATA 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm dc_parser_set_data
|
||||||
|
.Nd assigns parse data to a dive parser
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libdivecomputer
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In libdivecomputer/parser.h
|
||||||
|
.Ft dc_status_t
|
||||||
|
.Fo dc_parser_set_data
|
||||||
|
.Fa "dc_parser_t *parser"
|
||||||
|
.Fa "const unsigned char *data"
|
||||||
|
.Fa "unsigned int size"
|
||||||
|
.Fc
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
Assigns the binary sequence
|
||||||
|
.Fa data
|
||||||
|
of length
|
||||||
|
.Fa size
|
||||||
|
bytes to
|
||||||
|
.Fa parser ,
|
||||||
|
which was created with
|
||||||
|
.Xr dc_parser_new 3 .
|
||||||
|
How the data is parsed depends upon the values provided to
|
||||||
|
.Xr dc_parser_new 3 .
|
||||||
|
The data usually comes from the callback assigned to
|
||||||
|
.Xr dc_device_foreach 3 .
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
Returns
|
||||||
|
.Dv DC_STATUS_OK
|
||||||
|
on success and another code on failure.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr dc_device_foreach 3 ,
|
||||||
|
.Xr dc_parser_new 3
|
||||||
|
.Sh AUTHORS
|
||||||
|
The
|
||||||
|
.Lb libdivecomputer
|
||||||
|
library was written by
|
||||||
|
.An Jef Driesen ,
|
||||||
|
.Mt jef@libdivecomputer.org .
|
||||||
|
The manpages were written by
|
||||||
|
.An Kristaps Dzonsons ,
|
||||||
|
.Mt kristaps@bsd.lv .
|
||||||
@ -82,7 +82,9 @@ Iterate over all dives with
|
|||||||
.Xr dc_device_foreach 3 .
|
.Xr dc_device_foreach 3 .
|
||||||
.It
|
.It
|
||||||
For each iterated dive, create a new parser with
|
For each iterated dive, create a new parser with
|
||||||
.Xr dc_parser_new 3 .
|
.Xr dc_parser_new 3
|
||||||
|
and set the parsed data with
|
||||||
|
.Xr dc_parser_set_data 3 .
|
||||||
.It
|
.It
|
||||||
Get attributes of the parsed dive with
|
Get attributes of the parsed dive with
|
||||||
.Xr dc_parser_get_field 3 .
|
.Xr dc_parser_get_field 3 .
|
||||||
|
|||||||
@ -72,7 +72,6 @@ static const backend_table_t g_backends[] = {
|
|||||||
{"vtpro", DC_FAMILY_OCEANIC_VTPRO, 0x4245},
|
{"vtpro", DC_FAMILY_OCEANIC_VTPRO, 0x4245},
|
||||||
{"veo250", DC_FAMILY_OCEANIC_VEO250, 0x424C},
|
{"veo250", DC_FAMILY_OCEANIC_VEO250, 0x424C},
|
||||||
{"atom2", DC_FAMILY_OCEANIC_ATOM2, 0x4342},
|
{"atom2", DC_FAMILY_OCEANIC_ATOM2, 0x4342},
|
||||||
{"i330r", DC_FAMILY_PELAGIC_I330R, 0x4744},
|
|
||||||
{"nemo", DC_FAMILY_MARES_NEMO, 0},
|
{"nemo", DC_FAMILY_MARES_NEMO, 0},
|
||||||
{"puck", DC_FAMILY_MARES_PUCK, 7},
|
{"puck", DC_FAMILY_MARES_PUCK, 7},
|
||||||
{"darwin", DC_FAMILY_MARES_DARWIN, 0},
|
{"darwin", DC_FAMILY_MARES_DARWIN, 0},
|
||||||
|
|||||||
@ -80,12 +80,20 @@ dive_cb (const unsigned char *data, unsigned int size, const unsigned char *fing
|
|||||||
|
|
||||||
// Create the parser.
|
// Create the parser.
|
||||||
message ("Creating the parser.\n");
|
message ("Creating the parser.\n");
|
||||||
rc = dc_parser_new (&parser, divedata->device, data, size);
|
rc = dc_parser_new (&parser, divedata->device);
|
||||||
if (rc != DC_STATUS_SUCCESS) {
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
ERROR ("Error creating the parser.");
|
ERROR ("Error creating the parser.");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register the data.
|
||||||
|
message ("Registering the data.\n");
|
||||||
|
rc = dc_parser_set_data (parser, data, size);
|
||||||
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
|
ERROR ("Error registering the data.");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the dive data.
|
// Parse the dive data.
|
||||||
message ("Parsing the dive data.\n");
|
message ("Parsing the dive data.\n");
|
||||||
rc = dctool_output_write (divedata->output, parser, data, size, fingerprint, fsize);
|
rc = dctool_output_write (divedata->output, parser, data, size, fingerprint, fsize);
|
||||||
|
|||||||
@ -54,17 +54,17 @@ parse (dc_buffer_t *buffer, dc_context_t *context, dc_descriptor_t *descriptor,
|
|||||||
|
|
||||||
// Create the parser.
|
// Create the parser.
|
||||||
message ("Creating the parser.\n");
|
message ("Creating the parser.\n");
|
||||||
rc = dc_parser_new2 (&parser, context, descriptor, data, size);
|
rc = dc_parser_new2 (&parser, context, descriptor, devtime, systime);
|
||||||
if (rc != DC_STATUS_SUCCESS) {
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
ERROR ("Error creating the parser.");
|
ERROR ("Error creating the parser.");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the clock.
|
// Register the data.
|
||||||
message ("Setting the clock.\n");
|
message ("Registering the data.\n");
|
||||||
rc = dc_parser_set_clock (parser, devtime, systime);
|
rc = dc_parser_set_data (parser, data, size);
|
||||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
ERROR ("Error setting the clock.");
|
ERROR ("Error registering the data.");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -90,7 +90,7 @@ convert_volume (double value, dctool_units_t units)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sample_cb (dc_sample_type_t type, const dc_sample_value_t *value, void *userdata)
|
sample_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata)
|
||||||
{
|
{
|
||||||
static const char *events[] = {
|
static const char *events[] = {
|
||||||
"none", "deco", "rbt", "ascent", "ceiling", "workload", "transmitter",
|
"none", "deco", "rbt", "ascent", "ceiling", "workload", "transmitter",
|
||||||
@ -104,80 +104,64 @@ sample_cb (dc_sample_type_t type, const dc_sample_value_t *value, void *userdata
|
|||||||
|
|
||||||
sample_data_t *sampledata = (sample_data_t *) userdata;
|
sample_data_t *sampledata = (sample_data_t *) userdata;
|
||||||
|
|
||||||
unsigned int seconds = 0, milliseconds = 0;
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case DC_SAMPLE_TIME:
|
case DC_SAMPLE_TIME:
|
||||||
seconds = value->time / 1000;
|
|
||||||
milliseconds = value->time % 1000;
|
|
||||||
if (sampledata->nsamples++)
|
if (sampledata->nsamples++)
|
||||||
fprintf (sampledata->ostream, "</sample>\n");
|
fprintf (sampledata->ostream, "</sample>\n");
|
||||||
fprintf (sampledata->ostream, "<sample>\n");
|
fprintf (sampledata->ostream, "<sample>\n");
|
||||||
if (milliseconds) {
|
fprintf (sampledata->ostream, " <time>%02u:%02u</time>\n", value.time / 60, value.time % 60);
|
||||||
fprintf (sampledata->ostream, " <time>%02u:%02u.%03u</time>\n", seconds / 60, seconds % 60, milliseconds);
|
|
||||||
} else {
|
|
||||||
fprintf (sampledata->ostream, " <time>%02u:%02u</time>\n", seconds / 60, seconds % 60);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case DC_SAMPLE_DEPTH:
|
case DC_SAMPLE_DEPTH:
|
||||||
fprintf (sampledata->ostream, " <depth>%.2f</depth>\n",
|
fprintf (sampledata->ostream, " <depth>%.2f</depth>\n",
|
||||||
convert_depth(value->depth, sampledata->units));
|
convert_depth(value.depth, sampledata->units));
|
||||||
break;
|
break;
|
||||||
case DC_SAMPLE_PRESSURE:
|
case DC_SAMPLE_PRESSURE:
|
||||||
fprintf (sampledata->ostream, " <pressure tank=\"%u\">%.2f</pressure>\n",
|
fprintf (sampledata->ostream, " <pressure tank=\"%u\">%.2f</pressure>\n",
|
||||||
value->pressure.tank,
|
value.pressure.tank,
|
||||||
convert_pressure(value->pressure.value, sampledata->units));
|
convert_pressure(value.pressure.value, sampledata->units));
|
||||||
break;
|
break;
|
||||||
case DC_SAMPLE_TEMPERATURE:
|
case DC_SAMPLE_TEMPERATURE:
|
||||||
fprintf (sampledata->ostream, " <temperature>%.2f</temperature>\n",
|
fprintf (sampledata->ostream, " <temperature>%.2f</temperature>\n",
|
||||||
convert_temperature(value->temperature, sampledata->units));
|
convert_temperature(value.temperature, sampledata->units));
|
||||||
break;
|
break;
|
||||||
case DC_SAMPLE_EVENT:
|
case DC_SAMPLE_EVENT:
|
||||||
if (value->event.type != SAMPLE_EVENT_GASCHANGE && value->event.type != SAMPLE_EVENT_GASCHANGE2) {
|
if (value.event.type != SAMPLE_EVENT_GASCHANGE && value.event.type != SAMPLE_EVENT_GASCHANGE2) {
|
||||||
fprintf (sampledata->ostream, " <event type=\"%u\" time=\"%u\" flags=\"%u\" value=\"%u\">%s</event>\n",
|
fprintf (sampledata->ostream, " <event type=\"%u\" time=\"%u\" flags=\"%u\" value=\"%u\">%s</event>\n",
|
||||||
value->event.type, value->event.time, value->event.flags, value->event.value, events[value->event.type]);
|
value.event.type, value.event.time, value.event.flags, value.event.value, events[value.event.type]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DC_SAMPLE_RBT:
|
case DC_SAMPLE_RBT:
|
||||||
fprintf (sampledata->ostream, " <rbt>%u</rbt>\n", value->rbt);
|
fprintf (sampledata->ostream, " <rbt>%u</rbt>\n", value.rbt);
|
||||||
break;
|
break;
|
||||||
case DC_SAMPLE_HEARTBEAT:
|
case DC_SAMPLE_HEARTBEAT:
|
||||||
fprintf (sampledata->ostream, " <heartbeat>%u</heartbeat>\n", value->heartbeat);
|
fprintf (sampledata->ostream, " <heartbeat>%u</heartbeat>\n", value.heartbeat);
|
||||||
break;
|
break;
|
||||||
case DC_SAMPLE_BEARING:
|
case DC_SAMPLE_BEARING:
|
||||||
fprintf (sampledata->ostream, " <bearing>%u</bearing>\n", value->bearing);
|
fprintf (sampledata->ostream, " <bearing>%u</bearing>\n", value.bearing);
|
||||||
break;
|
break;
|
||||||
case DC_SAMPLE_VENDOR:
|
case DC_SAMPLE_VENDOR:
|
||||||
fprintf (sampledata->ostream, " <vendor type=\"%u\" size=\"%u\">", value->vendor.type, value->vendor.size);
|
fprintf (sampledata->ostream, " <vendor type=\"%u\" size=\"%u\">", value.vendor.type, value.vendor.size);
|
||||||
for (unsigned int i = 0; i < value->vendor.size; ++i)
|
for (unsigned int i = 0; i < value.vendor.size; ++i)
|
||||||
fprintf (sampledata->ostream, "%02X", ((const unsigned char *) value->vendor.data)[i]);
|
fprintf (sampledata->ostream, "%02X", ((const unsigned char *) value.vendor.data)[i]);
|
||||||
fprintf (sampledata->ostream, "</vendor>\n");
|
fprintf (sampledata->ostream, "</vendor>\n");
|
||||||
break;
|
break;
|
||||||
case DC_SAMPLE_SETPOINT:
|
case DC_SAMPLE_SETPOINT:
|
||||||
fprintf (sampledata->ostream, " <setpoint>%.2f</setpoint>\n", value->setpoint);
|
fprintf (sampledata->ostream, " <setpoint>%.2f</setpoint>\n", value.setpoint);
|
||||||
break;
|
break;
|
||||||
case DC_SAMPLE_PPO2:
|
case DC_SAMPLE_PPO2:
|
||||||
if (value->ppo2.sensor != DC_SENSOR_NONE) {
|
fprintf (sampledata->ostream, " <ppo2>%.2f</ppo2>\n", value.ppo2);
|
||||||
fprintf (sampledata->ostream, " <ppo2 sensor=\"%u\">%.2f</ppo2>\n", value->ppo2.sensor, value->ppo2.value);
|
|
||||||
} else {
|
|
||||||
fprintf (sampledata->ostream, " <ppo2>%.2f</ppo2>\n", value->ppo2.value);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case DC_SAMPLE_CNS:
|
case DC_SAMPLE_CNS:
|
||||||
fprintf (sampledata->ostream, " <cns>%.1f</cns>\n", value->cns * 100.0);
|
fprintf (sampledata->ostream, " <cns>%.1f</cns>\n", value.cns * 100.0);
|
||||||
break;
|
break;
|
||||||
case DC_SAMPLE_DECO:
|
case DC_SAMPLE_DECO:
|
||||||
fprintf (sampledata->ostream, " <deco time=\"%u\" depth=\"%.2f\">%s</deco>\n",
|
fprintf (sampledata->ostream, " <deco time=\"%u\" depth=\"%.2f\">%s</deco>\n",
|
||||||
value->deco.time,
|
value.deco.time,
|
||||||
convert_depth(value->deco.depth, sampledata->units),
|
convert_depth(value.deco.depth, sampledata->units),
|
||||||
decostop[value->deco.type]);
|
decostop[value.deco.type]);
|
||||||
if (value->deco.tts) {
|
|
||||||
fprintf (sampledata->ostream, " <tts>%u</tts>\n",
|
|
||||||
value->deco.tts);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case DC_SAMPLE_GASMIX:
|
case DC_SAMPLE_GASMIX:
|
||||||
fprintf (sampledata->ostream, " <gasmix>%u</gasmix>\n", value->gasmix);
|
fprintf (sampledata->ostream, " <gasmix>%u</gasmix>\n", value.gasmix);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -338,19 +322,11 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u
|
|||||||
"<gasmix>\n"
|
"<gasmix>\n"
|
||||||
" <he>%.1f</he>\n"
|
" <he>%.1f</he>\n"
|
||||||
" <o2>%.1f</o2>\n"
|
" <o2>%.1f</o2>\n"
|
||||||
" <n2>%.1f</n2>\n",
|
" <n2>%.1f</n2>\n"
|
||||||
|
"</gasmix>\n",
|
||||||
gasmix.helium * 100.0,
|
gasmix.helium * 100.0,
|
||||||
gasmix.oxygen * 100.0,
|
gasmix.oxygen * 100.0,
|
||||||
gasmix.nitrogen * 100.0);
|
gasmix.nitrogen * 100.0);
|
||||||
if (gasmix.usage) {
|
|
||||||
const char *usage[] = {"none", "oxygen", "diluent", "sidemount"};
|
|
||||||
fprintf (output->ostream,
|
|
||||||
" <usage>%s</usage>\n",
|
|
||||||
usage[gasmix.usage]);
|
|
||||||
}
|
|
||||||
fprintf (output->ostream,
|
|
||||||
"</gasmix>\n");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the tanks.
|
// Parse the tanks.
|
||||||
@ -378,12 +354,6 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u
|
|||||||
" <gasmix>%u</gasmix>\n",
|
" <gasmix>%u</gasmix>\n",
|
||||||
tank.gasmix);
|
tank.gasmix);
|
||||||
}
|
}
|
||||||
if (tank.usage) {
|
|
||||||
const char *usage[] = {"none", "oxygen", "diluent", "sidemount"};
|
|
||||||
fprintf (output->ostream,
|
|
||||||
" <usage>%s</usage>\n",
|
|
||||||
usage[tank.usage]);
|
|
||||||
}
|
|
||||||
if (tank.type != DC_TANKVOLUME_NONE) {
|
if (tank.type != DC_TANKVOLUME_NONE) {
|
||||||
fprintf (output->ostream,
|
fprintf (output->ostream,
|
||||||
" <type>%s</type>\n"
|
" <type>%s</type>\n"
|
||||||
@ -450,14 +420,8 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status != DC_STATUS_UNSUPPORTED) {
|
if (status != DC_STATUS_UNSUPPORTED) {
|
||||||
const char *names[] = {"fresh", "salt"};
|
fprintf (output->ostream, "<salinity type=\"%u\">%.1f</salinity>\n",
|
||||||
if (salinity.density) {
|
salinity.type, salinity.density);
|
||||||
fprintf (output->ostream, "<salinity density=\"%.1f\">%s</salinity>\n",
|
|
||||||
salinity.density, names[salinity.type]);
|
|
||||||
} else {
|
|
||||||
fprintf (output->ostream, "<salinity>%s</salinity>\n",
|
|
||||||
names[salinity.type]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the atmospheric pressure.
|
// Parse the atmospheric pressure.
|
||||||
|
|||||||
@ -36,6 +36,9 @@ atomics_cobalt_device_version (dc_device_t *device, unsigned char data[], unsign
|
|||||||
dc_status_t
|
dc_status_t
|
||||||
atomics_cobalt_device_set_simulation (dc_device_t *device, unsigned int simulation);
|
atomics_cobalt_device_set_simulation (dc_device_t *device, unsigned int simulation);
|
||||||
|
|
||||||
|
dc_status_t
|
||||||
|
atomics_cobalt_parser_set_calibration (dc_parser_t *parser, double atmospheric, double hydrostatic);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@ -33,21 +33,6 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#define DC_IOCTL_BLE_GET_NAME DC_IOCTL_IOR('b', 0, DC_IOCTL_SIZE_VARIABLE)
|
#define DC_IOCTL_BLE_GET_NAME DC_IOCTL_IOR('b', 0, DC_IOCTL_SIZE_VARIABLE)
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the bluetooth authentication PIN code.
|
|
||||||
*
|
|
||||||
* The data format is a NULL terminated string.
|
|
||||||
*/
|
|
||||||
#define DC_IOCTL_BLE_GET_PINCODE DC_IOCTL_IOR('b', 1, DC_IOCTL_SIZE_VARIABLE)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get/set the bluetooth authentication access code.
|
|
||||||
*
|
|
||||||
* The data format is a variable sized byte array.
|
|
||||||
*/
|
|
||||||
#define DC_IOCTL_BLE_GET_ACCESSCODE DC_IOCTL_IOR('b', 2, DC_IOCTL_SIZE_VARIABLE)
|
|
||||||
#define DC_IOCTL_BLE_SET_ACCESSCODE DC_IOCTL_IOW('b', 2, DC_IOCTL_SIZE_VARIABLE)
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@ -74,7 +74,6 @@ typedef enum dc_family_t {
|
|||||||
DC_FAMILY_OCEANIC_VTPRO = (4 << 16),
|
DC_FAMILY_OCEANIC_VTPRO = (4 << 16),
|
||||||
DC_FAMILY_OCEANIC_VEO250,
|
DC_FAMILY_OCEANIC_VEO250,
|
||||||
DC_FAMILY_OCEANIC_ATOM2,
|
DC_FAMILY_OCEANIC_ATOM2,
|
||||||
DC_FAMILY_PELAGIC_I330R,
|
|
||||||
/* Mares */
|
/* Mares */
|
||||||
DC_FAMILY_MARES_NEMO = (5 << 16),
|
DC_FAMILY_MARES_NEMO = (5 << 16),
|
||||||
DC_FAMILY_MARES_PUCK,
|
DC_FAMILY_MARES_PUCK,
|
||||||
|
|||||||
@ -29,96 +29,29 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
/**
|
|
||||||
* Opaque object representing a supported dive computer.
|
|
||||||
*/
|
|
||||||
typedef struct dc_descriptor_t dc_descriptor_t;
|
typedef struct dc_descriptor_t dc_descriptor_t;
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an iterator to enumerate the supported dive computers.
|
|
||||||
*
|
|
||||||
* @param[out] iterator A location to store the iterator.
|
|
||||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
|
||||||
* on failure.
|
|
||||||
*/
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
dc_descriptor_iterator (dc_iterator_t **iterator);
|
dc_descriptor_iterator (dc_iterator_t **iterator);
|
||||||
|
|
||||||
/**
|
|
||||||
* Free the device descriptor.
|
|
||||||
*
|
|
||||||
* @param[in] descriptor A valid device descriptor.
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
dc_descriptor_free (dc_descriptor_t *descriptor);
|
dc_descriptor_free (dc_descriptor_t *descriptor);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the vendor name of the dive computer.
|
|
||||||
*
|
|
||||||
* @param[in] descriptor A valid device descriptor.
|
|
||||||
* @returns The vendor name of the dive computer on success, or NULL on failure.
|
|
||||||
*/
|
|
||||||
const char *
|
const char *
|
||||||
dc_descriptor_get_vendor (dc_descriptor_t *descriptor);
|
dc_descriptor_get_vendor (dc_descriptor_t *descriptor);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the product name of the dive computer.
|
|
||||||
*
|
|
||||||
* @param[in] descriptor A valid device descriptor.
|
|
||||||
* @returns The product name of the dive computer on success, or NULL on
|
|
||||||
* failure.
|
|
||||||
*/
|
|
||||||
const char *
|
const char *
|
||||||
dc_descriptor_get_product (dc_descriptor_t *descriptor);
|
dc_descriptor_get_product (dc_descriptor_t *descriptor);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the family type of the dive computer.
|
|
||||||
*
|
|
||||||
* @param[in] descriptor A valid device descriptor.
|
|
||||||
* @returns The family type of the dive computer on success, or DC_FAMILY_NULL
|
|
||||||
* on failure.
|
|
||||||
*/
|
|
||||||
dc_family_t
|
dc_family_t
|
||||||
dc_descriptor_get_type (dc_descriptor_t *descriptor);
|
dc_descriptor_get_type (dc_descriptor_t *descriptor);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the model number of the dive computer.
|
|
||||||
*
|
|
||||||
* @param[in] descriptor A valid device descriptor.
|
|
||||||
* @returns The model number of the dive computer on success, or zero on
|
|
||||||
* failure.
|
|
||||||
*/
|
|
||||||
unsigned int
|
unsigned int
|
||||||
dc_descriptor_get_model (dc_descriptor_t *descriptor);
|
dc_descriptor_get_model (dc_descriptor_t *descriptor);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all transports supported by the dive computer.
|
|
||||||
*
|
|
||||||
* @param[in] descriptor A valid device descriptor.
|
|
||||||
* @returns A bitmask with all the transports supported by the dive computer on
|
|
||||||
* success, or DC_TRANSPORT_NONE on failure.
|
|
||||||
*/
|
|
||||||
unsigned int
|
unsigned int
|
||||||
dc_descriptor_get_transports (dc_descriptor_t *descriptor);
|
dc_descriptor_get_transports (dc_descriptor_t *descriptor);
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a low-level I/O device matches a supported dive computer.
|
|
||||||
*
|
|
||||||
* @param[in] descriptor A valid device descriptor.
|
|
||||||
* @param[in] transport The transport type of the I/O device.
|
|
||||||
* @param[in] userdata A pointer to a transport specific data structure:
|
|
||||||
* - DC_TRANSPORT_SERIAL: Name of the device node (string)
|
|
||||||
* - DC_TRANSPORT_USB: USB VID/PID (#dc_usb_desc_t)
|
|
||||||
* - DC_TRANSPORT_USBHID: USB VID/PID (#dc_usbhid_desc_t)
|
|
||||||
* - DC_TRANSPORT_IRDA: IrDA device name (string)
|
|
||||||
* - DC_TRANSPORT_BLUETOOTH: Bluetooth device name (string)
|
|
||||||
* - DC_TRANSPORT_BLE: Bluetooth device name (string)
|
|
||||||
* @returns Non-zero if the device matches a supported dive computer, or zero if
|
|
||||||
* there is no match.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@ -141,21 +141,12 @@ typedef struct dc_salinity_t {
|
|||||||
double density;
|
double density;
|
||||||
} dc_salinity_t;
|
} dc_salinity_t;
|
||||||
|
|
||||||
typedef enum dc_usage_t {
|
|
||||||
DC_USAGE_NONE,
|
|
||||||
DC_USAGE_OXYGEN,
|
|
||||||
DC_USAGE_DILUENT,
|
|
||||||
DC_USAGE_SIDEMOUNT,
|
|
||||||
} dc_usage_t;
|
|
||||||
|
|
||||||
typedef struct dc_gasmix_t {
|
typedef struct dc_gasmix_t {
|
||||||
double helium;
|
double helium;
|
||||||
double oxygen;
|
double oxygen;
|
||||||
double nitrogen;
|
double nitrogen;
|
||||||
dc_usage_t usage;
|
|
||||||
} dc_gasmix_t;
|
} dc_gasmix_t;
|
||||||
|
|
||||||
#define DC_SENSOR_NONE 0xFFFFFFFF
|
|
||||||
#define DC_GASMIX_UNKNOWN 0xFFFFFFFF
|
#define DC_GASMIX_UNKNOWN 0xFFFFFFFF
|
||||||
|
|
||||||
typedef enum dc_tankvolume_t {
|
typedef enum dc_tankvolume_t {
|
||||||
@ -194,7 +185,6 @@ typedef struct dc_tank_t {
|
|||||||
double workpressure; /* Work pressure (bar) */
|
double workpressure; /* Work pressure (bar) */
|
||||||
double beginpressure; /* Begin pressure (bar) */
|
double beginpressure; /* Begin pressure (bar) */
|
||||||
double endpressure; /* End pressure (bar) */
|
double endpressure; /* End pressure (bar) */
|
||||||
dc_usage_t usage;
|
|
||||||
} dc_tank_t;
|
} dc_tank_t;
|
||||||
|
|
||||||
typedef enum dc_decomodel_type_t {
|
typedef enum dc_decomodel_type_t {
|
||||||
@ -235,7 +225,7 @@ typedef struct dc_decomodel_t {
|
|||||||
} dc_decomodel_t;
|
} dc_decomodel_t;
|
||||||
|
|
||||||
typedef union dc_sample_value_t {
|
typedef union dc_sample_value_t {
|
||||||
unsigned int time; /* Milliseconds */
|
unsigned int time;
|
||||||
double depth;
|
double depth;
|
||||||
struct {
|
struct {
|
||||||
unsigned int tank;
|
unsigned int tank;
|
||||||
@ -257,29 +247,25 @@ typedef union dc_sample_value_t {
|
|||||||
const void *data;
|
const void *data;
|
||||||
} vendor;
|
} vendor;
|
||||||
double setpoint;
|
double setpoint;
|
||||||
struct {
|
double ppo2;
|
||||||
unsigned int sensor;
|
|
||||||
double value;
|
|
||||||
} ppo2;
|
|
||||||
double cns;
|
double cns;
|
||||||
struct {
|
struct {
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
unsigned int time;
|
unsigned int time;
|
||||||
double depth;
|
double depth;
|
||||||
unsigned int tts;
|
|
||||||
} deco;
|
} deco;
|
||||||
unsigned int gasmix; /* Gas mix index */
|
unsigned int gasmix; /* Gas mix index */
|
||||||
} dc_sample_value_t;
|
} dc_sample_value_t;
|
||||||
|
|
||||||
typedef struct dc_parser_t dc_parser_t;
|
typedef struct dc_parser_t dc_parser_t;
|
||||||
|
|
||||||
typedef void (*dc_sample_callback_t) (dc_sample_type_t type, const dc_sample_value_t *value, void *userdata);
|
typedef void (*dc_sample_callback_t) (dc_sample_type_t type, dc_sample_value_t value, void *userdata);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
dc_parser_new (dc_parser_t **parser, dc_device_t *device, const unsigned char data[], size_t size);
|
dc_parser_new (dc_parser_t **parser, dc_device_t *device);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
dc_parser_new2 (dc_parser_t **parser, dc_context_t *context, dc_descriptor_t *descriptor, const unsigned char data[], size_t size);
|
dc_parser_new2 (dc_parser_t **parser, dc_context_t *context, dc_descriptor_t *descriptor, unsigned int devtime, dc_ticks_t systime);
|
||||||
|
|
||||||
dc_family_t
|
dc_family_t
|
||||||
dc_parser_get_type (dc_parser_t *parser);
|
dc_parser_get_type (dc_parser_t *parser);
|
||||||
@ -293,6 +279,9 @@ dc_parser_set_atmospheric (dc_parser_t *parser, double atmospheric);
|
|||||||
dc_status_t
|
dc_status_t
|
||||||
dc_parser_set_density (dc_parser_t *parser, double density);
|
dc_parser_set_density (dc_parser_t *parser, double density);
|
||||||
|
|
||||||
|
dc_status_t
|
||||||
|
dc_parser_set_data (dc_parser_t *parser, const unsigned char *data, unsigned int size);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
dc_parser_get_datetime (dc_parser_t *parser, dc_datetime_t *datetime);
|
dc_parser_get_datetime (dc_parser_t *parser, dc_datetime_t *datetime);
|
||||||
|
|
||||||
|
|||||||
@ -35,6 +35,9 @@ extern "C" {
|
|||||||
dc_status_t
|
dc_status_t
|
||||||
reefnet_sensus_device_get_handshake (dc_device_t *device, unsigned char data[], unsigned int size);
|
reefnet_sensus_device_get_handshake (dc_device_t *device, unsigned char data[], unsigned int size);
|
||||||
|
|
||||||
|
dc_status_t
|
||||||
|
reefnet_sensus_parser_set_calibration (dc_parser_t *parser, double atmospheric, double hydrostatic);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@ -38,6 +38,9 @@ reefnet_sensuspro_device_get_handshake (dc_device_t *device, unsigned char data[
|
|||||||
dc_status_t
|
dc_status_t
|
||||||
reefnet_sensuspro_device_write_interval (dc_device_t *device, unsigned char interval);
|
reefnet_sensuspro_device_write_interval (dc_device_t *device, unsigned char interval);
|
||||||
|
|
||||||
|
dc_status_t
|
||||||
|
reefnet_sensuspro_parser_set_calibration (dc_parser_t *parser, double atmospheric, double hydrostatic);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@ -56,6 +56,9 @@ reefnet_sensusultra_device_write_parameter (dc_device_t *device, reefnet_sensusu
|
|||||||
dc_status_t
|
dc_status_t
|
||||||
reefnet_sensusultra_device_sense (dc_device_t *device, unsigned char data[], unsigned int size);
|
reefnet_sensusultra_device_sense (dc_device_t *device, unsigned char data[], unsigned int size);
|
||||||
|
|
||||||
|
dc_status_t
|
||||||
|
reefnet_sensusultra_parser_set_calibration (dc_parser_t *parser, double atmospheric, double hydrostatic);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@ -86,14 +86,6 @@ typedef enum dc_usb_recipient_t {
|
|||||||
DC_USB_RECIPIENT_OTHER = 0x03,
|
DC_USB_RECIPIENT_OTHER = 0x03,
|
||||||
} dc_usb_recipient_t;
|
} dc_usb_recipient_t;
|
||||||
|
|
||||||
/**
|
|
||||||
* USB device descriptor.
|
|
||||||
*/
|
|
||||||
typedef struct dc_usb_desc_t {
|
|
||||||
unsigned short vid;
|
|
||||||
unsigned short pid;
|
|
||||||
} dc_usb_desc_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opaque object representing a USB device.
|
* Opaque object representing a USB device.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -32,14 +32,6 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
/**
|
|
||||||
* USB HID device descriptor.
|
|
||||||
*/
|
|
||||||
typedef struct dc_usbhid_desc_t {
|
|
||||||
unsigned short vid;
|
|
||||||
unsigned short pid;
|
|
||||||
} dc_usbhid_desc_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opaque object representing a USB HID device.
|
* Opaque object representing a USB HID device.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -16,7 +16,7 @@ endif
|
|||||||
|
|
||||||
libdivecomputer_la_SOURCES = \
|
libdivecomputer_la_SOURCES = \
|
||||||
version.c \
|
version.c \
|
||||||
descriptor.c \
|
descriptor-private.h descriptor.c \
|
||||||
iostream-private.h iostream.c \
|
iostream-private.h iostream.c \
|
||||||
iterator-private.h iterator.c \
|
iterator-private.h iterator.c \
|
||||||
common-private.h common.c \
|
common-private.h common.c \
|
||||||
@ -43,7 +43,6 @@ libdivecomputer_la_SOURCES = \
|
|||||||
oceanic_atom2.h oceanic_atom2.c oceanic_atom2_parser.c \
|
oceanic_atom2.h oceanic_atom2.c oceanic_atom2_parser.c \
|
||||||
oceanic_veo250.h oceanic_veo250.c oceanic_veo250_parser.c \
|
oceanic_veo250.h oceanic_veo250.c oceanic_veo250_parser.c \
|
||||||
oceanic_vtpro.h oceanic_vtpro.c oceanic_vtpro_parser.c \
|
oceanic_vtpro.h oceanic_vtpro.c oceanic_vtpro_parser.c \
|
||||||
pelagic_i330r.h pelagic_i330r.c \
|
|
||||||
mares_common.h mares_common.c \
|
mares_common.h mares_common.c \
|
||||||
mares_nemo.h mares_nemo.c mares_nemo_parser.c \
|
mares_nemo.h mares_nemo.c mares_nemo_parser.c \
|
||||||
mares_puck.h mares_puck.c \
|
mares_puck.h mares_puck.c \
|
||||||
|
|||||||
11
src/array.c
11
src/array.c
@ -404,14 +404,3 @@ signextend (unsigned int value, unsigned int nbits)
|
|||||||
else
|
else
|
||||||
return value & mask;
|
return value & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
|
||||||
popcount (unsigned int value)
|
|
||||||
{
|
|
||||||
unsigned int count = 0;
|
|
||||||
while (value) {
|
|
||||||
value &= value - 1;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -126,9 +126,6 @@ dec2bcd (unsigned char value);
|
|||||||
unsigned int
|
unsigned int
|
||||||
signextend (unsigned int value, unsigned int nbits);
|
signextend (unsigned int value, unsigned int nbits);
|
||||||
|
|
||||||
unsigned int
|
|
||||||
popcount (unsigned int value);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@ -41,8 +41,6 @@
|
|||||||
|
|
||||||
#define FP_OFFSET 20
|
#define FP_OFFSET 20
|
||||||
|
|
||||||
#define SZ_HEADER 228
|
|
||||||
|
|
||||||
#define SZ_MEMORY1 (29 * 64 * 1024) // Cobalt 1
|
#define SZ_MEMORY1 (29 * 64 * 1024) // Cobalt 1
|
||||||
#define SZ_MEMORY2 (41 * 64 * 1024) // Cobalt 2
|
#define SZ_MEMORY2 (41 * 64 * 1024) // Cobalt 2
|
||||||
#define SZ_VERSION 14
|
#define SZ_VERSION 14
|
||||||
@ -349,12 +347,6 @@ atomics_cobalt_device_foreach (dc_device_t *abstract, dc_dive_callback_t callbac
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size < SZ_HEADER) {
|
|
||||||
ERROR (abstract->context, "Dive header is too small (%u).", size);
|
|
||||||
dc_buffer_free (buffer);
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memcmp (data + FP_OFFSET, device->fingerprint, sizeof (device->fingerprint)) == 0) {
|
if (memcmp (data + FP_OFFSET, device->fingerprint, sizeof (device->fingerprint)) == 0) {
|
||||||
dc_buffer_free (buffer);
|
dc_buffer_free (buffer);
|
||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
|
|||||||
@ -36,7 +36,7 @@ dc_status_t
|
|||||||
atomics_cobalt_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
atomics_cobalt_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
atomics_cobalt_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
atomics_cobalt_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,6 +43,7 @@ struct atomics_cobalt_parser_t {
|
|||||||
double hydrostatic;
|
double hydrostatic;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static dc_status_t atomics_cobalt_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t atomics_cobalt_parser_set_density (dc_parser_t *abstract, double density);
|
static dc_status_t atomics_cobalt_parser_set_density (dc_parser_t *abstract, double density);
|
||||||
static dc_status_t atomics_cobalt_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t atomics_cobalt_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
@ -51,6 +52,7 @@ static dc_status_t atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract,
|
|||||||
static const dc_parser_vtable_t atomics_cobalt_parser_vtable = {
|
static const dc_parser_vtable_t atomics_cobalt_parser_vtable = {
|
||||||
sizeof(atomics_cobalt_parser_t),
|
sizeof(atomics_cobalt_parser_t),
|
||||||
DC_FAMILY_ATOMICS_COBALT,
|
DC_FAMILY_ATOMICS_COBALT,
|
||||||
|
atomics_cobalt_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
atomics_cobalt_parser_set_density, /* set_density */
|
atomics_cobalt_parser_set_density, /* set_density */
|
||||||
@ -62,7 +64,7 @@ static const dc_parser_vtable_t atomics_cobalt_parser_vtable = {
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
atomics_cobalt_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
atomics_cobalt_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||||
{
|
{
|
||||||
atomics_cobalt_parser_t *parser = NULL;
|
atomics_cobalt_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -70,7 +72,7 @@ atomics_cobalt_parser_create (dc_parser_t **out, dc_context_t *context, const un
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (atomics_cobalt_parser_t *) dc_parser_allocate (context, &atomics_cobalt_parser_vtable, data, size);
|
parser = (atomics_cobalt_parser_t *) dc_parser_allocate (context, &atomics_cobalt_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -85,6 +87,27 @@ atomics_cobalt_parser_create (dc_parser_t **out, dc_context_t *context, const un
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
atomics_cobalt_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dc_status_t
|
||||||
|
atomics_cobalt_parser_set_calibration (dc_parser_t *abstract, double atmospheric, double hydrostatic)
|
||||||
|
{
|
||||||
|
atomics_cobalt_parser_t *parser = (atomics_cobalt_parser_t*) abstract;
|
||||||
|
|
||||||
|
if (!ISINSTANCE (abstract))
|
||||||
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
|
parser->hydrostatic = hydrostatic;
|
||||||
|
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
atomics_cobalt_parser_set_density (dc_parser_t *abstract, double density)
|
atomics_cobalt_parser_set_density (dc_parser_t *abstract, double density)
|
||||||
{
|
{
|
||||||
@ -148,7 +171,6 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
|
|||||||
*((unsigned int *) value) = p[0x2a];
|
*((unsigned int *) value) = p[0x2a];
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
gasmix->helium = p[SZ_HEADER + SZ_GASMIX * flags + 5] / 100.0;
|
gasmix->helium = p[SZ_HEADER + SZ_GASMIX * flags + 5] / 100.0;
|
||||||
gasmix->oxygen = p[SZ_HEADER + SZ_GASMIX * flags + 4] / 100.0;
|
gasmix->oxygen = p[SZ_HEADER + SZ_GASMIX * flags + 4] / 100.0;
|
||||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||||
@ -180,7 +202,6 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
|
|||||||
tank->gasmix = flags;
|
tank->gasmix = flags;
|
||||||
tank->beginpressure = array_uint16_le(p + 6) * PSI / BAR;
|
tank->beginpressure = array_uint16_le(p + 6) * PSI / BAR;
|
||||||
tank->endpressure = array_uint16_le(p + 14) * PSI / BAR;
|
tank->endpressure = array_uint16_le(p + 14) * PSI / BAR;
|
||||||
tank->usage = DC_USAGE_NONE;
|
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_DIVEMODE:
|
case DC_FIELD_DIVEMODE:
|
||||||
switch(p[0x24]) {
|
switch(p[0x24]) {
|
||||||
@ -255,19 +276,19 @@ atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
|||||||
|
|
||||||
// Time (seconds).
|
// Time (seconds).
|
||||||
time += interval;
|
time += interval;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Depth (1/1000 bar).
|
// Depth (1/1000 bar).
|
||||||
unsigned int depth = array_uint16_le (data + offset + 0);
|
unsigned int depth = array_uint16_le (data + offset + 0);
|
||||||
sample.depth = (signed int)(depth - atmospheric) * (BAR / 1000.0) / parser->hydrostatic;
|
sample.depth = (signed int)(depth - atmospheric) * (BAR / 1000.0) / parser->hydrostatic;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
// Pressure (1 psi).
|
// Pressure (1 psi).
|
||||||
unsigned int pressure = array_uint16_le (data + offset + 2);
|
unsigned int pressure = array_uint16_le (data + offset + 2);
|
||||||
sample.pressure.tank = tank;
|
sample.pressure.tank = tank;
|
||||||
sample.pressure.value = pressure * PSI / BAR;
|
sample.pressure.value = pressure * PSI / BAR;
|
||||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||||
|
|
||||||
// Current gas mix
|
// Current gas mix
|
||||||
unsigned int gasmix = data[offset + 4];
|
unsigned int gasmix = data[offset + 4];
|
||||||
@ -283,14 +304,14 @@ atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
|||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
}
|
}
|
||||||
sample.gasmix = idx;
|
sample.gasmix = idx;
|
||||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
gasmix_previous = gasmix;
|
gasmix_previous = gasmix;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temperature (1 °F).
|
// Temperature (1 °F).
|
||||||
unsigned int temperature = data[offset + 8];
|
unsigned int temperature = data[offset + 8];
|
||||||
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
|
|
||||||
// violation status
|
// violation status
|
||||||
sample.event.type = 0;
|
sample.event.type = 0;
|
||||||
@ -300,15 +321,15 @@ atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
|||||||
unsigned int violation = data[offset + 11];
|
unsigned int violation = data[offset + 11];
|
||||||
if (violation & 0x01) {
|
if (violation & 0x01) {
|
||||||
sample.event.type = SAMPLE_EVENT_ASCENT;
|
sample.event.type = SAMPLE_EVENT_ASCENT;
|
||||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||||
}
|
}
|
||||||
if (violation & 0x04) {
|
if (violation & 0x04) {
|
||||||
sample.event.type = SAMPLE_EVENT_CEILING;
|
sample.event.type = SAMPLE_EVENT_CEILING;
|
||||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||||
}
|
}
|
||||||
if (violation & 0x08) {
|
if (violation & 0x08) {
|
||||||
sample.event.type = SAMPLE_EVENT_PO2;
|
sample.event.type = SAMPLE_EVENT_PO2;
|
||||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NDL & deco
|
// NDL & deco
|
||||||
@ -323,8 +344,7 @@ atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
|||||||
sample.deco.type = DC_DECO_NDL;
|
sample.deco.type = DC_DECO_NDL;
|
||||||
sample.deco.time = ndl;
|
sample.deco.time = ndl;
|
||||||
sample.deco.depth = 0.0;
|
sample.deco.depth = 0.0;
|
||||||
sample.deco.tts = 0;
|
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
|
||||||
|
|
||||||
offset += SZ_SEGMENT;
|
offset += SZ_SEGMENT;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,6 +51,7 @@
|
|||||||
#include "context-private.h"
|
#include "context-private.h"
|
||||||
#include "iostream-private.h"
|
#include "iostream-private.h"
|
||||||
#include "iterator-private.h"
|
#include "iterator-private.h"
|
||||||
|
#include "descriptor-private.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -454,7 +455,7 @@ dc_bluetooth_iterator_next (dc_iterator_t *abstract, void *out)
|
|||||||
INFO (abstract->context, "Discover: address=" DC_ADDRESS_FORMAT ", name=%s",
|
INFO (abstract->context, "Discover: address=" DC_ADDRESS_FORMAT ", name=%s",
|
||||||
address, name ? name : "");
|
address, name ? name : "");
|
||||||
|
|
||||||
if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_BLUETOOTH, name)) {
|
if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_BLUETOOTH, name, NULL)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -31,8 +31,6 @@
|
|||||||
|
|
||||||
#define ISINSTANCE(device) dc_device_isinstance((device), &citizen_aqualand_device_vtable)
|
#define ISINSTANCE(device) dc_device_isinstance((device), &citizen_aqualand_device_vtable)
|
||||||
|
|
||||||
#define SZ_HEADER 32
|
|
||||||
|
|
||||||
typedef struct citizen_aqualand_device_t {
|
typedef struct citizen_aqualand_device_t {
|
||||||
dc_device_t base;
|
dc_device_t base;
|
||||||
dc_iostream_t *iostream;
|
dc_iostream_t *iostream;
|
||||||
@ -202,12 +200,6 @@ citizen_aqualand_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
|
|||||||
unsigned char *data = dc_buffer_get_data (buffer);
|
unsigned char *data = dc_buffer_get_data (buffer);
|
||||||
unsigned int size = dc_buffer_get_size (buffer);
|
unsigned int size = dc_buffer_get_size (buffer);
|
||||||
|
|
||||||
if (size < SZ_HEADER) {
|
|
||||||
ERROR (abstract->context, "Dive header is too small (%u).", size);
|
|
||||||
dc_buffer_free (buffer);
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback && memcmp (data + 0x05, device->fingerprint, sizeof (device->fingerprint)) != 0) {
|
if (callback && memcmp (data + 0x05, device->fingerprint, sizeof (device->fingerprint)) != 0) {
|
||||||
callback (data, size, data + 0x05, sizeof (device->fingerprint), userdata);
|
callback (data, size, data + 0x05, sizeof (device->fingerprint), userdata);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,7 +35,7 @@ dc_status_t
|
|||||||
citizen_aqualand_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
citizen_aqualand_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
citizen_aqualand_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
citizen_aqualand_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,7 @@ typedef struct citizen_aqualand_parser_t {
|
|||||||
dc_parser_t base;
|
dc_parser_t base;
|
||||||
} citizen_aqualand_parser_t;
|
} citizen_aqualand_parser_t;
|
||||||
|
|
||||||
|
static dc_status_t citizen_aqualand_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t citizen_aqualand_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t citizen_aqualand_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t citizen_aqualand_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t citizen_aqualand_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t citizen_aqualand_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t citizen_aqualand_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -43,6 +44,7 @@ static dc_status_t citizen_aqualand_parser_samples_foreach (dc_parser_t *abstrac
|
|||||||
static const dc_parser_vtable_t citizen_aqualand_parser_vtable = {
|
static const dc_parser_vtable_t citizen_aqualand_parser_vtable = {
|
||||||
sizeof(citizen_aqualand_parser_t),
|
sizeof(citizen_aqualand_parser_t),
|
||||||
DC_FAMILY_CITIZEN_AQUALAND,
|
DC_FAMILY_CITIZEN_AQUALAND,
|
||||||
|
citizen_aqualand_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -54,7 +56,7 @@ static const dc_parser_vtable_t citizen_aqualand_parser_vtable = {
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
citizen_aqualand_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
citizen_aqualand_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||||
{
|
{
|
||||||
citizen_aqualand_parser_t *parser = NULL;
|
citizen_aqualand_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -62,7 +64,7 @@ citizen_aqualand_parser_create (dc_parser_t **out, dc_context_t *context, const
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (citizen_aqualand_parser_t *) dc_parser_allocate (context, &citizen_aqualand_parser_vtable, data, size);
|
parser = (citizen_aqualand_parser_t *) dc_parser_allocate (context, &citizen_aqualand_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -74,6 +76,13 @@ citizen_aqualand_parser_create (dc_parser_t **out, dc_context_t *context, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
citizen_aqualand_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
citizen_aqualand_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
citizen_aqualand_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -232,15 +241,15 @@ citizen_aqualand_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
|
|
||||||
// Time
|
// Time
|
||||||
time += interval;
|
time += interval;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Depth
|
// Depth
|
||||||
if (metric)
|
if (metric)
|
||||||
sample.depth = depth / 10.0;
|
sample.depth = depth / 10.0;
|
||||||
else
|
else
|
||||||
sample.depth = depth * FEET;
|
sample.depth = depth * FEET;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
// Temperature
|
// Temperature
|
||||||
if (time % 300 == 0) {
|
if (time % 300 == 0) {
|
||||||
@ -251,7 +260,7 @@ citizen_aqualand_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
sample.temperature = temperature / 10.0;
|
sample.temperature = temperature / 10.0;
|
||||||
else
|
else
|
||||||
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -603,7 +603,7 @@ cochran_commander_profile_size(cochran_commander_device_t *device, cochran_data_
|
|||||||
// Corrupt dive, guess the end address
|
// Corrupt dive, guess the end address
|
||||||
sample_end_address = cochran_commander_guess_sample_end_address(device, data, dive_num);
|
sample_end_address = cochran_commander_guess_sample_end_address(device, data, dive_num);
|
||||||
|
|
||||||
return ringbuffer_distance(sample_start_address, sample_end_address, DC_RINGBUFFER_EMPTY, device->layout->rb_profile_begin, device->layout->rb_profile_end);
|
return ringbuffer_distance(sample_start_address, sample_end_address, 0, device->layout->rb_profile_begin, device->layout->rb_profile_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -965,7 +965,7 @@ cochran_commander_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
|
|||||||
last_start_address = base + array_uint32_le(data.config + layout->cf_last_log );
|
last_start_address = base + array_uint32_le(data.config + layout->cf_last_log );
|
||||||
|
|
||||||
// Create the ringbuffer stream.
|
// Create the ringbuffer stream.
|
||||||
status = dc_rbstream_new (&rbstream, abstract, 1, layout->rbstream_size, layout->rb_profile_begin, layout->rb_profile_end, last_start_address, DC_RBSTREAM_BACKWARD);
|
status = dc_rbstream_new (&rbstream, abstract, 1, layout->rbstream_size, layout->rb_profile_begin, layout->rb_profile_end, last_start_address);
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
ERROR (abstract->context, "Failed to create the ringbuffer stream.");
|
ERROR (abstract->context, "Failed to create the ringbuffer stream.");
|
||||||
goto error;
|
goto error;
|
||||||
|
|||||||
@ -35,7 +35,7 @@ dc_status_t
|
|||||||
cochran_commander_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
cochran_commander_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
cochran_commander_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
cochran_commander_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -99,6 +99,7 @@ typedef struct cochran_commander_parser_t {
|
|||||||
unsigned int nevents;
|
unsigned int nevents;
|
||||||
} cochran_commander_parser_t ;
|
} cochran_commander_parser_t ;
|
||||||
|
|
||||||
|
static dc_status_t cochran_commander_parser_set_data (dc_parser_t *parser, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t cochran_commander_parser_get_datetime (dc_parser_t *parser, dc_datetime_t *datetime);
|
static dc_status_t cochran_commander_parser_get_datetime (dc_parser_t *parser, dc_datetime_t *datetime);
|
||||||
static dc_status_t cochran_commander_parser_get_field (dc_parser_t *parser, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t cochran_commander_parser_get_field (dc_parser_t *parser, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t cochran_commander_parser_samples_foreach (dc_parser_t *parser, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t cochran_commander_parser_samples_foreach (dc_parser_t *parser, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -106,6 +107,7 @@ static dc_status_t cochran_commander_parser_samples_foreach (dc_parser_t *parser
|
|||||||
static const dc_parser_vtable_t cochran_commander_parser_vtable = {
|
static const dc_parser_vtable_t cochran_commander_parser_vtable = {
|
||||||
sizeof(cochran_commander_parser_t),
|
sizeof(cochran_commander_parser_t),
|
||||||
DC_FAMILY_COCHRAN_COMMANDER,
|
DC_FAMILY_COCHRAN_COMMANDER,
|
||||||
|
cochran_commander_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -313,7 +315,7 @@ cochran_commander_handle_event (cochran_commander_parser_t *parser, unsigned cha
|
|||||||
sample.event.time = 0;
|
sample.event.time = 0;
|
||||||
sample.event.value = 0;
|
sample.event.value = 0;
|
||||||
sample.event.flags = event->flag;
|
sample.event.flags = event->flag;
|
||||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,7 +352,7 @@ cochran_commander_backparse(cochran_commander_parser_t *parser, const unsigned c
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
cochran_commander_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
cochran_commander_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||||
{
|
{
|
||||||
cochran_commander_parser_t *parser = NULL;
|
cochran_commander_parser_t *parser = NULL;
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
dc_status_t status = DC_STATUS_SUCCESS;
|
||||||
@ -359,7 +361,7 @@ cochran_commander_parser_create (dc_parser_t **out, dc_context_t *context, const
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (cochran_commander_parser_t *) dc_parser_allocate (context, &cochran_commander_parser_vtable, data, size);
|
parser = (cochran_commander_parser_t *) dc_parser_allocate (context, &cochran_commander_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -405,6 +407,13 @@ error_free:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
cochran_commander_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
cochran_commander_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
cochran_commander_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -505,7 +514,6 @@ cochran_commander_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
|
|||||||
// Gas percentages are decimal and encoded as
|
// Gas percentages are decimal and encoded as
|
||||||
// highbyte = integer portion
|
// highbyte = integer portion
|
||||||
// lowbyte = decimal portion, divide by 256 to get decimal value
|
// lowbyte = decimal portion, divide by 256 to get decimal value
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
gasmix->oxygen = array_uint16_le (data + layout->oxygen + 2 * flags) / 256.0 / 100;
|
gasmix->oxygen = array_uint16_le (data + layout->oxygen + 2 * flags) / 256.0 / 100;
|
||||||
if (layout->helium == UNSUPPORTED) {
|
if (layout->helium == UNSUPPORTED) {
|
||||||
gasmix->helium = 0;
|
gasmix->helium = 0;
|
||||||
@ -570,26 +578,26 @@ cochran_commander_parser_samples_foreach_tm (dc_parser_t *abstract, dc_sample_ca
|
|||||||
unsigned int temp = samples[0]; // Half degrees F
|
unsigned int temp = samples[0]; // Half degrees F
|
||||||
unsigned int depth = samples[1]; // Half feet
|
unsigned int depth = samples[1]; // Half feet
|
||||||
|
|
||||||
last_sample_time = sample.time = time * 1000;
|
last_sample_time = sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
sample.depth = (depth / 2.0) * FEET;
|
sample.depth = (depth / 2.0) * FEET;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
sample.temperature = (temp / 2.0 - 32.0) / 1.8;
|
sample.temperature = (temp / 2.0 - 32.0) / 1.8;
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
|
|
||||||
sample.gasmix = 0;
|
sample.gasmix = 0;
|
||||||
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
|
|
||||||
while (offset < size) {
|
while (offset < size) {
|
||||||
const unsigned char *s = samples + offset;
|
const unsigned char *s = samples + offset;
|
||||||
|
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (last_sample_time != sample.time) {
|
if (last_sample_time != sample.time) {
|
||||||
// We haven't issued this time yet.
|
// We haven't issued this time yet.
|
||||||
last_sample_time = sample.time;
|
last_sample_time = sample.time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*s & 0x80) {
|
if (*s & 0x80) {
|
||||||
@ -607,8 +615,7 @@ cochran_commander_parser_samples_foreach_tm (dc_parser_t *abstract, dc_sample_ca
|
|||||||
sample.deco.type = DC_DECO_DECOSTOP;
|
sample.deco.type = DC_DECO_DECOSTOP;
|
||||||
sample.deco.time = 60; // We don't know the duration
|
sample.deco.time = 60; // We don't know the duration
|
||||||
sample.deco.depth = deco_ceiling * FEET;
|
sample.deco.depth = deco_ceiling * FEET;
|
||||||
sample.deco.tts = 0;
|
if (callback) callback(DC_SAMPLE_DECO, sample, userdata);
|
||||||
if (callback) callback(DC_SAMPLE_DECO, &sample, userdata);
|
|
||||||
break;
|
break;
|
||||||
case 0xAD: // Increment ceiling (shallower)
|
case 0xAD: // Increment ceiling (shallower)
|
||||||
deco_ceiling -= 10; // feet
|
deco_ceiling -= 10; // feet
|
||||||
@ -616,8 +623,7 @@ cochran_commander_parser_samples_foreach_tm (dc_parser_t *abstract, dc_sample_ca
|
|||||||
sample.deco.type = DC_DECO_DECOSTOP;
|
sample.deco.type = DC_DECO_DECOSTOP;
|
||||||
sample.deco.depth = deco_ceiling * FEET;
|
sample.deco.depth = deco_ceiling * FEET;
|
||||||
sample.deco.time = 60; // We don't know the duration
|
sample.deco.time = 60; // We don't know the duration
|
||||||
sample.deco.tts = 0;
|
if (callback) callback(DC_SAMPLE_DECO, sample, userdata);
|
||||||
if (callback) callback(DC_SAMPLE_DECO, &sample, userdata);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cochran_commander_handle_event(parser, s[0], callback, userdata);
|
cochran_commander_handle_event(parser, s[0], callback, userdata);
|
||||||
@ -630,7 +636,7 @@ cochran_commander_parser_samples_foreach_tm (dc_parser_t *abstract, dc_sample_ca
|
|||||||
else
|
else
|
||||||
temp += (*s & 0x0f);
|
temp += (*s & 0x0f);
|
||||||
sample.temperature = (temp / 2.0 - 32.0) / 1.8;
|
sample.temperature = (temp / 2.0 - 32.0) / 1.8;
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
offset++;
|
offset++;
|
||||||
@ -644,7 +650,7 @@ cochran_commander_parser_samples_foreach_tm (dc_parser_t *abstract, dc_sample_ca
|
|||||||
depth += s[0] & 0x3f;
|
depth += s[0] & 0x3f;
|
||||||
|
|
||||||
sample.depth = (depth / 2.0) * FEET;
|
sample.depth = (depth / 2.0) * FEET;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
offset++;
|
offset++;
|
||||||
time += sample_interval;
|
time += sample_interval;
|
||||||
@ -708,27 +714,27 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
|
|||||||
start_depth = array_uint16_le (data + layout->start_depth) / 256.0;
|
start_depth = array_uint16_le (data + layout->start_depth) / 256.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_sample_time = sample.time = time * 1000;
|
last_sample_time = sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
sample.depth = start_depth * FEET;
|
sample.depth = start_depth * FEET;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
sample.temperature = (data[layout->start_temp] - 32.0) / 1.8;
|
sample.temperature = (data[layout->start_temp] - 32.0) / 1.8;
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
|
|
||||||
sample.gasmix = 0;
|
sample.gasmix = 0;
|
||||||
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
unsigned int last_gasmix = sample.gasmix;
|
unsigned int last_gasmix = sample.gasmix;
|
||||||
|
|
||||||
while (offset < size) {
|
while (offset < size) {
|
||||||
const unsigned char *s = samples + offset;
|
const unsigned char *s = samples + offset;
|
||||||
|
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (last_sample_time != sample.time) {
|
if (last_sample_time != sample.time) {
|
||||||
// We haven't issued this time yet.
|
// We haven't issued this time yet.
|
||||||
last_sample_time = sample.time;
|
last_sample_time = sample.time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If corrupt_dive end before offset
|
// If corrupt_dive end before offset
|
||||||
@ -768,8 +774,7 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
|
|||||||
sample.deco.type = DC_DECO_DECOSTOP;
|
sample.deco.type = DC_DECO_DECOSTOP;
|
||||||
sample.deco.time = (array_uint16_le(s + 3) + 1) * 60;
|
sample.deco.time = (array_uint16_le(s + 3) + 1) * 60;
|
||||||
sample.deco.depth = deco_ceiling * FEET;
|
sample.deco.depth = deco_ceiling * FEET;
|
||||||
sample.deco.tts = 0;
|
if (callback) callback(DC_SAMPLE_DECO, sample, userdata);
|
||||||
if (callback) callback(DC_SAMPLE_DECO, &sample, userdata);
|
|
||||||
break;
|
break;
|
||||||
case 0xAD: // Increment ceiling (shallower)
|
case 0xAD: // Increment ceiling (shallower)
|
||||||
deco_ceiling -= 10; // feet
|
deco_ceiling -= 10; // feet
|
||||||
@ -777,8 +782,7 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
|
|||||||
sample.deco.type = DC_DECO_DECOSTOP;
|
sample.deco.type = DC_DECO_DECOSTOP;
|
||||||
sample.deco.depth = deco_ceiling * FEET;
|
sample.deco.depth = deco_ceiling * FEET;
|
||||||
sample.deco.time = (array_uint16_le(s + 3) + 1) * 60;
|
sample.deco.time = (array_uint16_le(s + 3) + 1) * 60;
|
||||||
sample.deco.tts = 0;
|
if (callback) callback(DC_SAMPLE_DECO, sample, userdata);
|
||||||
if (callback) callback(DC_SAMPLE_DECO, &sample, userdata);
|
|
||||||
break;
|
break;
|
||||||
case 0xC0: // Switched to FO2 21% mode (surface)
|
case 0xC0: // Switched to FO2 21% mode (surface)
|
||||||
// Event seen upon surfacing
|
// Event seen upon surfacing
|
||||||
@ -787,14 +791,14 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
|
|||||||
case 0xEF: // Switched to gas blend 2
|
case 0xEF: // Switched to gas blend 2
|
||||||
if (last_gasmix != 1) {
|
if (last_gasmix != 1) {
|
||||||
sample.gasmix = 1;
|
sample.gasmix = 1;
|
||||||
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
last_gasmix = sample.gasmix;
|
last_gasmix = sample.gasmix;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xF3: // Switched to gas blend 1
|
case 0xF3: // Switched to gas blend 1
|
||||||
if (last_gasmix != 0) {
|
if (last_gasmix != 0) {
|
||||||
sample.gasmix = 0;
|
sample.gasmix = 0;
|
||||||
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
last_gasmix = sample.gasmix;
|
last_gasmix = sample.gasmix;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -814,7 +818,7 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
|
|||||||
depth += (s[0] & 0x3f);
|
depth += (s[0] & 0x3f);
|
||||||
|
|
||||||
sample.depth = (start_depth + depth / 4.0) * FEET;
|
sample.depth = (start_depth + depth / 4.0) * FEET;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
// Ascent rate is logged in the 0th sample, temp in the 1st, repeat.
|
// Ascent rate is logged in the 0th sample, temp in the 1st, repeat.
|
||||||
if (time % 2 == 0) {
|
if (time % 2 == 0) {
|
||||||
@ -830,7 +834,7 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
|
|||||||
double temperature = s[1] / 2.0 + 20.0;
|
double temperature = s[1] / 2.0 + 20.0;
|
||||||
sample.temperature = (temperature - 32.0) / 1.8;
|
sample.temperature = (temperature - 32.0) / 1.8;
|
||||||
|
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cochran EMC models store NDL and deco stop time
|
// Cochran EMC models store NDL and deco stop time
|
||||||
@ -851,8 +855,7 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
|
|||||||
sample.deco.type = DC_DECO_NDL;
|
sample.deco.type = DC_DECO_NDL;
|
||||||
sample.deco.time = deco_time * 60;
|
sample.deco.time = deco_time * 60;
|
||||||
sample.deco.depth = 0;
|
sample.deco.depth = 0;
|
||||||
sample.deco.tts = 0;
|
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 23:
|
case 23:
|
||||||
@ -862,8 +865,7 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
|
|||||||
sample.deco.type = DC_DECO_DECOSTOP;
|
sample.deco.type = DC_DECO_DECOSTOP;
|
||||||
sample.deco.depth = deco_ceiling * FEET;
|
sample.deco.depth = deco_ceiling * FEET;
|
||||||
sample.deco.time = deco_time * 60;
|
sample.deco.time = deco_time * 60;
|
||||||
sample.deco.tts = 0;
|
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,8 +38,6 @@
|
|||||||
#define SZ_PACKET 0x80
|
#define SZ_PACKET 0x80
|
||||||
#define SZ_PAGE (SZ_PACKET / 4)
|
#define SZ_PAGE (SZ_PACKET / 4)
|
||||||
|
|
||||||
#define SZ_HEADER 32
|
|
||||||
|
|
||||||
#define IQ700 0x05
|
#define IQ700 0x05
|
||||||
#define EDY 0x08
|
#define EDY 0x08
|
||||||
|
|
||||||
@ -432,7 +430,7 @@ cressi_edy_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the number of logbook items.
|
// Get the number of logbook items.
|
||||||
unsigned int count = ringbuffer_distance (first, last, DC_RINGBUFFER_EMPTY, layout->rb_logbook_begin, layout->rb_logbook_end) + 1;
|
unsigned int count = ringbuffer_distance (first, last, 0, layout->rb_logbook_begin, layout->rb_logbook_end) + 1;
|
||||||
|
|
||||||
// Get the profile pointer.
|
// Get the profile pointer.
|
||||||
unsigned int eop = array_uint_le (logbook + layout->config + 2, layout->rb_logbook_size) * SZ_PAGE + layout->rb_profile_begin;
|
unsigned int eop = array_uint_le (logbook + layout->config + 2, layout->rb_logbook_size) * SZ_PAGE + layout->rb_profile_begin;
|
||||||
@ -457,7 +455,7 @@ cressi_edy_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the profile length.
|
// Get the profile length.
|
||||||
unsigned int length = ringbuffer_distance (current, previous, DC_RINGBUFFER_FULL, layout->rb_profile_begin, layout->rb_profile_end);
|
unsigned int length = ringbuffer_distance (current, previous, 1, layout->rb_profile_begin, layout->rb_profile_end);
|
||||||
|
|
||||||
// Check for a ringbuffer overflow.
|
// Check for a ringbuffer overflow.
|
||||||
if (total + length > layout->rb_profile_end - layout->rb_profile_begin) {
|
if (total + length > layout->rb_profile_end - layout->rb_profile_begin) {
|
||||||
@ -481,7 +479,7 @@ cressi_edy_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
|
|||||||
|
|
||||||
// Create the ringbuffer stream.
|
// Create the ringbuffer stream.
|
||||||
dc_rbstream_t *rbstream = NULL;
|
dc_rbstream_t *rbstream = NULL;
|
||||||
rc = dc_rbstream_new (&rbstream, abstract, SZ_PAGE, SZ_PACKET, layout->rb_profile_begin, layout->rb_profile_end, eop, DC_RBSTREAM_BACKWARD);
|
rc = dc_rbstream_new (&rbstream, abstract, SZ_PAGE, SZ_PACKET, layout->rb_profile_begin, layout->rb_profile_end, eop);
|
||||||
if (rc != DC_STATUS_SUCCESS) {
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
ERROR (abstract->context, "Failed to create the ringbuffer stream.");
|
ERROR (abstract->context, "Failed to create the ringbuffer stream.");
|
||||||
return rc;
|
return rc;
|
||||||
@ -510,7 +508,7 @@ cressi_edy_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the profile length.
|
// Get the profile length.
|
||||||
unsigned int length = ringbuffer_distance (current, previous, DC_RINGBUFFER_FULL, layout->rb_profile_begin, layout->rb_profile_end);
|
unsigned int length = ringbuffer_distance (current, previous, 1, layout->rb_profile_begin, layout->rb_profile_end);
|
||||||
|
|
||||||
// Move to the begin of the current dive.
|
// Move to the begin of the current dive.
|
||||||
offset -= length;
|
offset -= length;
|
||||||
@ -524,13 +522,6 @@ cressi_edy_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length < SZ_HEADER) {
|
|
||||||
ERROR (abstract->context, "Dive header is too small (%u).", length);
|
|
||||||
dc_rbstream_free (rbstream);
|
|
||||||
free (buffer);
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char *p = buffer + offset;
|
unsigned char *p = buffer + offset;
|
||||||
|
|
||||||
if (memcmp (p, device->fingerprint, sizeof (device->fingerprint)) == 0)
|
if (memcmp (p, device->fingerprint, sizeof (device->fingerprint)) == 0)
|
||||||
|
|||||||
@ -35,7 +35,7 @@ dc_status_t
|
|||||||
cressi_edy_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
cressi_edy_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
cressi_edy_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
cressi_edy_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,8 +31,6 @@
|
|||||||
#define IQ700 0x05
|
#define IQ700 0x05
|
||||||
#define EDY 0x08
|
#define EDY 0x08
|
||||||
|
|
||||||
#define SZ_HEADER 32
|
|
||||||
|
|
||||||
typedef struct cressi_edy_parser_t cressi_edy_parser_t;
|
typedef struct cressi_edy_parser_t cressi_edy_parser_t;
|
||||||
|
|
||||||
struct cressi_edy_parser_t {
|
struct cressi_edy_parser_t {
|
||||||
@ -40,6 +38,7 @@ struct cressi_edy_parser_t {
|
|||||||
unsigned int model;
|
unsigned int model;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static dc_status_t cressi_edy_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t cressi_edy_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t cressi_edy_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t cressi_edy_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t cressi_edy_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -47,6 +46,7 @@ static dc_status_t cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_
|
|||||||
static const dc_parser_vtable_t cressi_edy_parser_vtable = {
|
static const dc_parser_vtable_t cressi_edy_parser_vtable = {
|
||||||
sizeof(cressi_edy_parser_t),
|
sizeof(cressi_edy_parser_t),
|
||||||
DC_FAMILY_CRESSI_EDY,
|
DC_FAMILY_CRESSI_EDY,
|
||||||
|
cressi_edy_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -73,7 +73,7 @@ cressi_edy_parser_count_gasmixes (const unsigned char *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
cressi_edy_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
cressi_edy_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||||
{
|
{
|
||||||
cressi_edy_parser_t *parser = NULL;
|
cressi_edy_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ cressi_edy_parser_create (dc_parser_t **out, dc_context_t *context, const unsign
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (cressi_edy_parser_t *) dc_parser_allocate (context, &cressi_edy_parser_vtable, data, size);
|
parser = (cressi_edy_parser_t *) dc_parser_allocate (context, &cressi_edy_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -96,10 +96,17 @@ cressi_edy_parser_create (dc_parser_t **out, dc_context_t *context, const unsign
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
cressi_edy_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
cressi_edy_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
cressi_edy_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
if (abstract->size < SZ_HEADER)
|
if (abstract->size < 32)
|
||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
|
|
||||||
const unsigned char *p = abstract->data;
|
const unsigned char *p = abstract->data;
|
||||||
@ -123,7 +130,7 @@ cressi_edy_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign
|
|||||||
{
|
{
|
||||||
cressi_edy_parser_t *parser = (cressi_edy_parser_t *) abstract;
|
cressi_edy_parser_t *parser = (cressi_edy_parser_t *) abstract;
|
||||||
|
|
||||||
if (abstract->size < SZ_HEADER)
|
if (abstract->size < 32)
|
||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
|
|
||||||
const unsigned char *p = abstract->data;
|
const unsigned char *p = abstract->data;
|
||||||
@ -145,7 +152,6 @@ cressi_edy_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign
|
|||||||
*((unsigned int *) value) = cressi_edy_parser_count_gasmixes(p);
|
*((unsigned int *) value) = cressi_edy_parser_count_gasmixes(p);
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
gasmix->helium = 0.0;
|
gasmix->helium = 0.0;
|
||||||
gasmix->oxygen = bcd2dec (p[0x17 - flags]) / 100.0;
|
gasmix->oxygen = bcd2dec (p[0x17 - flags]) / 100.0;
|
||||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||||
@ -182,7 +188,7 @@ cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
|||||||
unsigned int ngasmixes = cressi_edy_parser_count_gasmixes(data);
|
unsigned int ngasmixes = cressi_edy_parser_count_gasmixes(data);
|
||||||
unsigned int gasmix = 0xFFFFFFFF;
|
unsigned int gasmix = 0xFFFFFFFF;
|
||||||
|
|
||||||
unsigned int offset = SZ_HEADER;
|
unsigned int offset = 32;
|
||||||
while (offset + 2 <= size) {
|
while (offset + 2 <= size) {
|
||||||
dc_sample_value_t sample = {0};
|
dc_sample_value_t sample = {0};
|
||||||
|
|
||||||
@ -195,13 +201,13 @@ cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
|||||||
|
|
||||||
// Time (seconds).
|
// Time (seconds).
|
||||||
time += interval;
|
time += interval;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Depth (1/10 m).
|
// Depth (1/10 m).
|
||||||
unsigned int depth = bcd2dec (data[offset + 0] & 0x0F) * 100 + bcd2dec (data[offset + 1]);
|
unsigned int depth = bcd2dec (data[offset + 0] & 0x0F) * 100 + bcd2dec (data[offset + 1]);
|
||||||
sample.depth = depth / 10.0;
|
sample.depth = depth / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
// Current gasmix
|
// Current gasmix
|
||||||
if (ngasmixes) {
|
if (ngasmixes) {
|
||||||
@ -214,7 +220,7 @@ cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
|||||||
}
|
}
|
||||||
if (idx != gasmix) {
|
if (idx != gasmix) {
|
||||||
sample.gasmix = idx;
|
sample.gasmix = idx;
|
||||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
gasmix = idx;
|
gasmix = idx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,7 +35,7 @@ dc_status_t
|
|||||||
cressi_goa_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
cressi_goa_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
cressi_goa_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
cressi_goa_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,6 +62,7 @@ typedef struct cressi_goa_layout_t {
|
|||||||
unsigned int temperature;
|
unsigned int temperature;
|
||||||
} cressi_goa_layout_t;
|
} cressi_goa_layout_t;
|
||||||
|
|
||||||
|
static dc_status_t cressi_goa_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t cressi_goa_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t cressi_goa_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t cressi_goa_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t cressi_goa_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t cressi_goa_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t cressi_goa_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -69,6 +70,7 @@ static dc_status_t cressi_goa_parser_samples_foreach (dc_parser_t *abstract, dc_
|
|||||||
static const dc_parser_vtable_t cressi_goa_parser_vtable = {
|
static const dc_parser_vtable_t cressi_goa_parser_vtable = {
|
||||||
sizeof(cressi_goa_parser_t),
|
sizeof(cressi_goa_parser_t),
|
||||||
DC_FAMILY_CRESSI_GOA,
|
DC_FAMILY_CRESSI_GOA,
|
||||||
|
cressi_goa_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -126,7 +128,7 @@ static const cressi_goa_layout_t layouts[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
cressi_goa_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
cressi_goa_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||||
{
|
{
|
||||||
cressi_goa_parser_t *parser = NULL;
|
cressi_goa_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -134,7 +136,7 @@ cressi_goa_parser_create (dc_parser_t **out, dc_context_t *context, const unsign
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (cressi_goa_parser_t *) dc_parser_allocate (context, &cressi_goa_parser_vtable, data, size);
|
parser = (cressi_goa_parser_t *) dc_parser_allocate (context, &cressi_goa_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -147,6 +149,12 @@ cressi_goa_parser_create (dc_parser_t **out, dc_context_t *context, const unsign
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
cressi_goa_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
cressi_goa_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
cressi_goa_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -242,7 +250,6 @@ cressi_goa_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign
|
|||||||
*((unsigned int *) value) = ngasmixes;
|
*((unsigned int *) value) = ngasmixes;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
gasmix->helium = 0.0;
|
gasmix->helium = 0.0;
|
||||||
gasmix->oxygen = data[layout->gasmix + 2 * flags + 1] / 100.0;
|
gasmix->oxygen = data[layout->gasmix + 2 * flags + 1] / 100.0;
|
||||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||||
@ -322,25 +329,25 @@ cressi_goa_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
|||||||
|
|
||||||
if (complete) {
|
if (complete) {
|
||||||
// Time (seconds).
|
// Time (seconds).
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Temperature (1/10 °C).
|
// Temperature (1/10 °C).
|
||||||
if (have_temperature) {
|
if (have_temperature) {
|
||||||
sample.temperature = temperature / 10.0;
|
sample.temperature = temperature / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
have_temperature = 0;
|
have_temperature = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Depth (1/10 m).
|
// Depth (1/10 m).
|
||||||
sample.depth = depth / 10.0;
|
sample.depth = depth / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
// Gas change
|
// Gas change
|
||||||
if (divemode == SCUBA || divemode == NITROX) {
|
if (divemode == SCUBA || divemode == NITROX) {
|
||||||
if (gasmix != gasmix_previous) {
|
if (gasmix != gasmix_previous) {
|
||||||
sample.gasmix = gasmix;
|
sample.gasmix = gasmix;
|
||||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
gasmix_previous = gasmix;
|
gasmix_previous = gasmix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
#define RB_PROFILE_BEGIN 0x1438
|
#define RB_PROFILE_BEGIN 0x1438
|
||||||
#define RB_PROFILE_END SZ_MEMORY
|
#define RB_PROFILE_END SZ_MEMORY
|
||||||
#define RB_PROFILE_DISTANCE(a,b) ringbuffer_distance (a, b, DC_RINGBUFFER_EMPTY, RB_PROFILE_BEGIN, RB_PROFILE_END)
|
#define RB_PROFILE_DISTANCE(a,b) ringbuffer_distance (a, b, 0, RB_PROFILE_BEGIN, RB_PROFILE_END)
|
||||||
|
|
||||||
#define MAXRETRIES 4
|
#define MAXRETRIES 4
|
||||||
#define PACKETSIZE 32
|
#define PACKETSIZE 32
|
||||||
|
|||||||
@ -35,7 +35,7 @@ dc_status_t
|
|||||||
cressi_leonardo_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
cressi_leonardo_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
cressi_leonardo_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
cressi_leonardo_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,7 @@ struct cressi_leonardo_parser_t {
|
|||||||
unsigned int model;
|
unsigned int model;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static dc_status_t cressi_leonardo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t cressi_leonardo_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t cressi_leonardo_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t cressi_leonardo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t cressi_leonardo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -46,6 +47,7 @@ static dc_status_t cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract
|
|||||||
static const dc_parser_vtable_t cressi_leonardo_parser_vtable = {
|
static const dc_parser_vtable_t cressi_leonardo_parser_vtable = {
|
||||||
sizeof(cressi_leonardo_parser_t),
|
sizeof(cressi_leonardo_parser_t),
|
||||||
DC_FAMILY_CRESSI_LEONARDO,
|
DC_FAMILY_CRESSI_LEONARDO,
|
||||||
|
cressi_leonardo_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -57,7 +59,7 @@ static const dc_parser_vtable_t cressi_leonardo_parser_vtable = {
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
cressi_leonardo_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
cressi_leonardo_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||||
{
|
{
|
||||||
cressi_leonardo_parser_t *parser = NULL;
|
cressi_leonardo_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -65,7 +67,7 @@ cressi_leonardo_parser_create (dc_parser_t **out, dc_context_t *context, const u
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (cressi_leonardo_parser_t *) dc_parser_allocate (context, &cressi_leonardo_parser_vtable, data, size);
|
parser = (cressi_leonardo_parser_t *) dc_parser_allocate (context, &cressi_leonardo_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -79,6 +81,13 @@ cressi_leonardo_parser_create (dc_parser_t **out, dc_context_t *context, const u
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
cressi_leonardo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
cressi_leonardo_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
cressi_leonardo_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -137,7 +146,6 @@ cressi_leonardo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, u
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
gasmix->helium = 0.0;
|
gasmix->helium = 0.0;
|
||||||
gasmix->oxygen = data[0x19] / 100.0;
|
gasmix->oxygen = data[0x19] / 100.0;
|
||||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||||
@ -188,12 +196,12 @@ cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
|
|||||||
|
|
||||||
// Time (seconds).
|
// Time (seconds).
|
||||||
time += surftime;
|
time += surftime;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Depth (1/10 m).
|
// Depth (1/10 m).
|
||||||
sample.depth = 0.0;
|
sample.depth = 0.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
offset += 4;
|
offset += 4;
|
||||||
} else {
|
} else {
|
||||||
@ -203,17 +211,17 @@ cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
|
|||||||
|
|
||||||
// Time (seconds).
|
// Time (seconds).
|
||||||
time += interval;
|
time += interval;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Depth (1/10 m).
|
// Depth (1/10 m).
|
||||||
sample.depth = depth / 10.0;
|
sample.depth = depth / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
// Gas change.
|
// Gas change.
|
||||||
if (gasmix != gasmix_previous) {
|
if (gasmix != gasmix_previous) {
|
||||||
sample.gasmix = gasmix;
|
sample.gasmix = gasmix;
|
||||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
gasmix_previous = gasmix;
|
gasmix_previous = gasmix;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +231,7 @@ cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
|
|||||||
sample.event.time = 0;
|
sample.event.time = 0;
|
||||||
sample.event.flags = 0;
|
sample.event.flags = 0;
|
||||||
sample.event.value = ascent;
|
sample.event.value = ascent;
|
||||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += 2;
|
offset += 2;
|
||||||
|
|||||||
@ -36,7 +36,7 @@ dc_status_t
|
|||||||
deepblu_cosmiq_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
deepblu_cosmiq_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
deepblu_cosmiq_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
deepblu_cosmiq_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,6 +41,7 @@ typedef struct deepblu_cosmiq_parser_t {
|
|||||||
double hydrostatic;
|
double hydrostatic;
|
||||||
} deepblu_cosmiq_parser_t;
|
} deepblu_cosmiq_parser_t;
|
||||||
|
|
||||||
|
static dc_status_t deepblu_cosmiq_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t deepblu_cosmiq_parser_set_density (dc_parser_t *abstract, double density);
|
static dc_status_t deepblu_cosmiq_parser_set_density (dc_parser_t *abstract, double density);
|
||||||
static dc_status_t deepblu_cosmiq_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t deepblu_cosmiq_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t deepblu_cosmiq_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t deepblu_cosmiq_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
@ -49,6 +50,7 @@ static dc_status_t deepblu_cosmiq_parser_samples_foreach (dc_parser_t *abstract,
|
|||||||
static const dc_parser_vtable_t deepblu_cosmiq_parser_vtable = {
|
static const dc_parser_vtable_t deepblu_cosmiq_parser_vtable = {
|
||||||
sizeof(deepblu_cosmiq_parser_t),
|
sizeof(deepblu_cosmiq_parser_t),
|
||||||
DC_FAMILY_DEEPBLU_COSMIQ,
|
DC_FAMILY_DEEPBLU_COSMIQ,
|
||||||
|
deepblu_cosmiq_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
deepblu_cosmiq_parser_set_density, /* set_density */
|
deepblu_cosmiq_parser_set_density, /* set_density */
|
||||||
@ -59,7 +61,7 @@ static const dc_parser_vtable_t deepblu_cosmiq_parser_vtable = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
deepblu_cosmiq_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
deepblu_cosmiq_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||||
{
|
{
|
||||||
deepblu_cosmiq_parser_t *parser = NULL;
|
deepblu_cosmiq_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -67,7 +69,7 @@ deepblu_cosmiq_parser_create (dc_parser_t **out, dc_context_t *context, const un
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (deepblu_cosmiq_parser_t *) dc_parser_allocate (context, &deepblu_cosmiq_parser_vtable, data, size);
|
parser = (deepblu_cosmiq_parser_t *) dc_parser_allocate (context, &deepblu_cosmiq_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -81,6 +83,12 @@ deepblu_cosmiq_parser_create (dc_parser_t **out, dc_context_t *context, const un
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
deepblu_cosmiq_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
deepblu_cosmiq_parser_set_density (dc_parser_t *abstract, double density)
|
deepblu_cosmiq_parser_set_density (dc_parser_t *abstract, double density)
|
||||||
{
|
{
|
||||||
@ -143,7 +151,6 @@ deepblu_cosmiq_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
|
|||||||
*((unsigned int *) value) = mode == SCUBA;
|
*((unsigned int *) value) = mode == SCUBA;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
gasmix->oxygen = data[3] / 100.0;
|
gasmix->oxygen = data[3] / 100.0;
|
||||||
gasmix->helium = 0.0;
|
gasmix->helium = 0.0;
|
||||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||||
@ -197,14 +204,14 @@ deepblu_cosmiq_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
|||||||
offset += SZ_SAMPLE;
|
offset += SZ_SAMPLE;
|
||||||
|
|
||||||
time += interval;
|
time += interval;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
sample.depth = (signed int) (depth - atmospheric) * (BAR / 1000.0) / parser->hydrostatic;
|
sample.depth = (signed int) (depth - atmospheric) * (BAR / 1000.0) / parser->hydrostatic;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
sample.temperature = temperature / 10.0;
|
sample.temperature = temperature / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
|
|||||||
@ -35,7 +35,7 @@ dc_status_t
|
|||||||
deepsix_excursion_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t *iostream);
|
deepsix_excursion_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
deepsix_excursion_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
deepsix_excursion_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -112,6 +112,7 @@ typedef struct deepsix_excursion_parser_t {
|
|||||||
deepsix_excursion_gasmix_t gasmix[MAX_GASMIXES];
|
deepsix_excursion_gasmix_t gasmix[MAX_GASMIXES];
|
||||||
} deepsix_excursion_parser_t;
|
} deepsix_excursion_parser_t;
|
||||||
|
|
||||||
|
static dc_status_t deepsix_excursion_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t deepsix_excursion_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t deepsix_excursion_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t deepsix_excursion_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t deepsix_excursion_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t deepsix_excursion_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t deepsix_excursion_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -121,6 +122,7 @@ static dc_status_t deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abs
|
|||||||
static const dc_parser_vtable_t deepsix_parser_vtable = {
|
static const dc_parser_vtable_t deepsix_parser_vtable = {
|
||||||
sizeof(deepsix_excursion_parser_t),
|
sizeof(deepsix_excursion_parser_t),
|
||||||
DC_FAMILY_DEEPSIX_EXCURSION,
|
DC_FAMILY_DEEPSIX_EXCURSION,
|
||||||
|
deepsix_excursion_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -183,7 +185,7 @@ deepsix_excursion_find_gasmix(deepsix_excursion_parser_t *parser, unsigned int o
|
|||||||
}
|
}
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
deepsix_excursion_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
deepsix_excursion_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||||
{
|
{
|
||||||
deepsix_excursion_parser_t *parser = NULL;
|
deepsix_excursion_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -191,7 +193,7 @@ deepsix_excursion_parser_create (dc_parser_t **out, dc_context_t *context, const
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (deepsix_excursion_parser_t *) dc_parser_allocate (context, &deepsix_parser_vtable, data, size);
|
parser = (deepsix_excursion_parser_t *) dc_parser_allocate (context, &deepsix_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -211,6 +213,23 @@ deepsix_excursion_parser_create (dc_parser_t **out, dc_context_t *context, const
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
deepsix_excursion_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
deepsix_excursion_parser_t *parser = (deepsix_excursion_parser_t *) abstract;
|
||||||
|
|
||||||
|
// Reset the cache.
|
||||||
|
parser->cached = 0;
|
||||||
|
parser->ngasmixes = 0;
|
||||||
|
for (unsigned int i = 0; i < MAX_GASMIXES; ++i) {
|
||||||
|
parser->gasmix[i].id = 0;
|
||||||
|
parser->gasmix[i].oxygen = 0;
|
||||||
|
parser->gasmix[i].helium = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
deepsix_excursion_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
deepsix_excursion_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -303,7 +322,6 @@ deepsix_excursion_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
|
|||||||
*((unsigned int *) value) = parser->ngasmixes;
|
*((unsigned int *) value) = parser->ngasmixes;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
||||||
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
||||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||||
@ -405,11 +423,11 @@ deepsix_excursion_parser_samples_foreach_v0 (dc_parser_t *abstract, dc_sample_ca
|
|||||||
|
|
||||||
if (type == TEMPERATURE) {
|
if (type == TEMPERATURE) {
|
||||||
time += interval;
|
time += interval;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback(DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
sample.depth = pressure_to_depth(depth, atmospheric, DENSITY);
|
sample.depth = pressure_to_depth(depth, atmospheric, DENSITY);
|
||||||
if (callback) callback(DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == ALARM) {
|
if (type == ALARM) {
|
||||||
@ -422,11 +440,11 @@ deepsix_excursion_parser_samples_foreach_v0 (dc_parser_t *abstract, dc_sample_ca
|
|||||||
length = 8;
|
length = 8;
|
||||||
} else if (temperature >= 10) {
|
} else if (temperature >= 10) {
|
||||||
sample.temperature = temperature / 10.0;
|
sample.temperature = temperature / 10.0;
|
||||||
if (callback) callback(DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sample.temperature = temperature / 10.0;
|
sample.temperature = temperature / 10.0;
|
||||||
if (callback) callback(DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
}
|
}
|
||||||
} else if (type == DECO) {
|
} else if (type == DECO) {
|
||||||
unsigned int deco = array_uint16_le(data + offset + 4);
|
unsigned int deco = array_uint16_le(data + offset + 4);
|
||||||
@ -436,7 +454,7 @@ deepsix_excursion_parser_samples_foreach_v0 (dc_parser_t *abstract, dc_sample_ca
|
|||||||
} else if (type == CNS) {
|
} else if (type == CNS) {
|
||||||
unsigned int cns = array_uint16_le(data + offset + 4);
|
unsigned int cns = array_uint16_le(data + offset + 4);
|
||||||
sample.cns = cns / 100.0;
|
sample.cns = cns / 100.0;
|
||||||
if (callback) callback(DC_SAMPLE_CNS, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_CNS, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += length;
|
offset += length;
|
||||||
@ -573,12 +591,12 @@ deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abstract, dc_sample_ca
|
|||||||
|
|
||||||
// Time (seconds).
|
// Time (seconds).
|
||||||
time += samplerate;
|
time += samplerate;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
unsigned int depth = array_uint16_le (data + offset);
|
unsigned int depth = array_uint16_le (data + offset);
|
||||||
sample.depth = pressure_to_depth(depth, atmospheric, density);
|
sample.depth = pressure_to_depth(depth, atmospheric, density);
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
|
|
||||||
// event info
|
// event info
|
||||||
@ -646,7 +664,7 @@ deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abstract, dc_sample_ca
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (sample.event.type != SAMPLE_EVENT_NONE) {
|
if (sample.event.type != SAMPLE_EVENT_NONE) {
|
||||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -668,7 +686,7 @@ deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abstract, dc_sample_ca
|
|||||||
}
|
}
|
||||||
|
|
||||||
sample.gasmix = mix_idx;
|
sample.gasmix = mix_idx;
|
||||||
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
break;
|
break;
|
||||||
case EVENT_SAMPLES_MISSED:
|
case EVENT_SAMPLES_MISSED:
|
||||||
count = array_uint16_le(data + offset + event_offset);
|
count = array_uint16_le(data + offset + event_offset);
|
||||||
@ -709,12 +727,12 @@ deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abstract, dc_sample_ca
|
|||||||
case SAMPLE_TEMPERATURE:
|
case SAMPLE_TEMPERATURE:
|
||||||
value = array_uint16_le(data + offset);
|
value = array_uint16_le(data + offset);
|
||||||
sample.temperature = value / 10.0;
|
sample.temperature = value / 10.0;
|
||||||
if (callback) callback(DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
break;
|
break;
|
||||||
case SAMPLE_CNS:
|
case SAMPLE_CNS:
|
||||||
value = array_uint16_le(data + offset);
|
value = array_uint16_le(data + offset);
|
||||||
sample.cns = value / 10000.0;
|
sample.cns = value / 10000.0;
|
||||||
if (callback) callback (DC_SAMPLE_CNS, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
|
||||||
break;
|
break;
|
||||||
case SAMPLE_DECO_NDL:
|
case SAMPLE_DECO_NDL:
|
||||||
deco_flags = data[offset];
|
deco_flags = data[offset];
|
||||||
@ -734,7 +752,7 @@ deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abstract, dc_sample_ca
|
|||||||
sample.deco.depth = 0;
|
sample.deco.depth = 0;
|
||||||
sample.deco.time = deco_ndl_tts;
|
sample.deco.time = deco_ndl_tts;
|
||||||
}
|
}
|
||||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* libdivecomputer
|
* libdivecomputer
|
||||||
*
|
*
|
||||||
* Copyright (C) 2023 Janice McLaughlin
|
* Copyright (C) 2017 Jef Driesen
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -19,22 +19,30 @@
|
|||||||
* MA 02110-1301 USA
|
* MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PELAGIC_I330R_H
|
#ifndef DC_DESCRIPTOR_PRIVATE_H
|
||||||
#define PELAGIC_I330R_H
|
#define DC_DESCRIPTOR_PRIVATE_H
|
||||||
|
|
||||||
#include <libdivecomputer/context.h>
|
#include <libdivecomputer/descriptor.h>
|
||||||
#include <libdivecomputer/iostream.h>
|
|
||||||
#include <libdivecomputer/device.h>
|
|
||||||
#include <libdivecomputer/parser.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
dc_status_t
|
typedef struct dc_usb_desc_t {
|
||||||
pelagic_i330r_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
unsigned short vid;
|
||||||
|
unsigned short pid;
|
||||||
|
} dc_usb_desc_t;
|
||||||
|
|
||||||
|
typedef struct dc_usb_params_t {
|
||||||
|
unsigned int interface;
|
||||||
|
unsigned char endpoint_in;
|
||||||
|
unsigned char endpoint_out;
|
||||||
|
} dc_usb_params_t;
|
||||||
|
|
||||||
|
int
|
||||||
|
dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif /* PELAGIC_I330R_H */
|
#endif /* DC_DESCRIPTOR_PRIVATE_H */
|
||||||
158
src/descriptor.c
158
src/descriptor.c
@ -23,10 +23,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <libdivecomputer/descriptor.h>
|
#include "descriptor-private.h"
|
||||||
#include <libdivecomputer/usbhid.h>
|
|
||||||
#include <libdivecomputer/usb.h>
|
|
||||||
|
|
||||||
#include "iterator-private.h"
|
#include "iterator-private.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
@ -39,26 +36,36 @@
|
|||||||
values, \
|
values, \
|
||||||
C_ARRAY_SIZE(values) - isnullterminated, \
|
C_ARRAY_SIZE(values) - isnullterminated, \
|
||||||
C_ARRAY_ITEMSIZE(values), \
|
C_ARRAY_ITEMSIZE(values), \
|
||||||
match)
|
match, \
|
||||||
|
NULL, NULL, 0)
|
||||||
|
|
||||||
|
#define DC_FILTER_INTERNAL_WITH_PARAMS(key, values, isnullterminated, match, params_dst, params_src) \
|
||||||
|
dc_filter_internal( \
|
||||||
|
key, \
|
||||||
|
values, \
|
||||||
|
C_ARRAY_SIZE(values) - isnullterminated, \
|
||||||
|
C_ARRAY_ITEMSIZE(values), \
|
||||||
|
match, \
|
||||||
|
params_dst, params_src, sizeof *(params_src))
|
||||||
|
|
||||||
typedef int (*dc_match_t)(const void *, const void *);
|
typedef int (*dc_match_t)(const void *, const void *);
|
||||||
|
|
||||||
typedef int (*dc_filter_t) (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
typedef int (*dc_filter_t) (dc_transport_t transport, const void *userdata, void *params);
|
||||||
|
|
||||||
static int dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
static int dc_filter_uwatec (dc_transport_t transport, const void *userdata, void *params);
|
||||||
static int dc_filter_suunto (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
static int dc_filter_suunto (dc_transport_t transport, const void *userdata, void *params);
|
||||||
static int dc_filter_shearwater (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
static int dc_filter_shearwater (dc_transport_t transport, const void *userdata, void *params);
|
||||||
static int dc_filter_hw (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
static int dc_filter_hw (dc_transport_t transport, const void *userdata, void *params);
|
||||||
static int dc_filter_tecdiving (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
static int dc_filter_tecdiving (dc_transport_t transport, const void *userdata, void *params);
|
||||||
static int dc_filter_mares (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
static int dc_filter_mares (dc_transport_t transport, const void *userdata, void *params);
|
||||||
static int dc_filter_divesystem (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
static int dc_filter_divesystem (dc_transport_t transport, const void *userdata, void *params);
|
||||||
static int dc_filter_oceanic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
static int dc_filter_oceanic (dc_transport_t transport, const void *userdata, void *params);
|
||||||
static int dc_filter_mclean (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
static int dc_filter_mclean (dc_transport_t transport, const void *userdata, void *params);
|
||||||
static int dc_filter_atomic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
static int dc_filter_atomic (dc_transport_t transport, const void *userdata, void *params);
|
||||||
static int dc_filter_deepsix (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
static int dc_filter_deepsix (dc_transport_t transport, const void *userdata, void *params);
|
||||||
static int dc_filter_deepblu (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
static int dc_filter_deepblu (dc_transport_t transport, const void *userdata, void *params);
|
||||||
static int dc_filter_oceans (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
static int dc_filter_oceans (dc_transport_t transport, const void *userdata, void *params);
|
||||||
static int dc_filter_divesoft (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
static int dc_filter_divesoft (dc_transport_t transport, const void *userdata, void *params);
|
||||||
|
|
||||||
static dc_status_t dc_descriptor_iterator_next (dc_iterator_t *iterator, void *item);
|
static dc_status_t dc_descriptor_iterator_next (dc_iterator_t *iterator, void *item);
|
||||||
|
|
||||||
@ -170,10 +177,7 @@ static const dc_descriptor_t g_descriptors[] = {
|
|||||||
{"Scubapro", "G2 TEK", DC_FAMILY_UWATEC_SMART, 0x31, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
|
{"Scubapro", "G2 TEK", DC_FAMILY_UWATEC_SMART, 0x31, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
|
||||||
{"Scubapro", "G2", DC_FAMILY_UWATEC_SMART, 0x32, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
|
{"Scubapro", "G2", DC_FAMILY_UWATEC_SMART, 0x32, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
|
||||||
{"Scubapro", "G2 Console", DC_FAMILY_UWATEC_SMART, 0x32, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
|
{"Scubapro", "G2 Console", DC_FAMILY_UWATEC_SMART, 0x32, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
|
||||||
{"Scubapro", "G3", DC_FAMILY_UWATEC_SMART, 0x34, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
|
|
||||||
{"Scubapro", "G2 HUD", DC_FAMILY_UWATEC_SMART, 0x42, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
|
{"Scubapro", "G2 HUD", DC_FAMILY_UWATEC_SMART, 0x42, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
|
||||||
{"Scubapro", "Luna 2.0 AI", DC_FAMILY_UWATEC_SMART, 0x50, DC_TRANSPORT_BLE, dc_filter_uwatec},
|
|
||||||
{"Scubapro", "Luna 2.0", DC_FAMILY_UWATEC_SMART, 0x51, DC_TRANSPORT_BLE, dc_filter_uwatec},
|
|
||||||
/* Reefnet */
|
/* Reefnet */
|
||||||
{"Reefnet", "Sensus", DC_FAMILY_REEFNET_SENSUS, 1, DC_TRANSPORT_SERIAL, NULL},
|
{"Reefnet", "Sensus", DC_FAMILY_REEFNET_SENSUS, 1, DC_TRANSPORT_SERIAL, NULL},
|
||||||
{"Reefnet", "Sensus Pro", DC_FAMILY_REEFNET_SENSUSPRO, 2, DC_TRANSPORT_SERIAL, NULL},
|
{"Reefnet", "Sensus Pro", DC_FAMILY_REEFNET_SENSUSPRO, 2, DC_TRANSPORT_SERIAL, NULL},
|
||||||
@ -272,9 +276,6 @@ static const dc_descriptor_t g_descriptors[] = {
|
|||||||
{"Aqualung", "i470TC", DC_FAMILY_OCEANIC_ATOM2, 0x4743, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_oceanic},
|
{"Aqualung", "i470TC", DC_FAMILY_OCEANIC_ATOM2, 0x4743, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_oceanic},
|
||||||
{"Aqualung", "i200C", DC_FAMILY_OCEANIC_ATOM2, 0x4749, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_oceanic},
|
{"Aqualung", "i200C", DC_FAMILY_OCEANIC_ATOM2, 0x4749, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_oceanic},
|
||||||
{"Oceanic", "Geo Air", DC_FAMILY_OCEANIC_ATOM2, 0x474B, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_oceanic},
|
{"Oceanic", "Geo Air", DC_FAMILY_OCEANIC_ATOM2, 0x474B, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_oceanic},
|
||||||
/* Pelagic I330R */
|
|
||||||
{"Apeks", "DSX", DC_FAMILY_PELAGIC_I330R, 0x4741, DC_TRANSPORT_BLE, dc_filter_oceanic},
|
|
||||||
{"Aqualung", "i330R", DC_FAMILY_PELAGIC_I330R, 0x4744, DC_TRANSPORT_BLE, dc_filter_oceanic},
|
|
||||||
/* Mares Nemo */
|
/* Mares Nemo */
|
||||||
{"Mares", "Nemo", DC_FAMILY_MARES_NEMO, 0, DC_TRANSPORT_SERIAL, NULL},
|
{"Mares", "Nemo", DC_FAMILY_MARES_NEMO, 0, DC_TRANSPORT_SERIAL, NULL},
|
||||||
{"Mares", "Nemo Steel", DC_FAMILY_MARES_NEMO, 0, DC_TRANSPORT_SERIAL, NULL},
|
{"Mares", "Nemo Steel", DC_FAMILY_MARES_NEMO, 0, DC_TRANSPORT_SERIAL, NULL},
|
||||||
@ -307,10 +308,6 @@ static const dc_descriptor_t g_descriptors[] = {
|
|||||||
{"Mares", "Smart Air", DC_FAMILY_MARES_ICONHD , 0x24, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_mares},
|
{"Mares", "Smart Air", DC_FAMILY_MARES_ICONHD , 0x24, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_mares},
|
||||||
{"Mares", "Quad", DC_FAMILY_MARES_ICONHD , 0x29, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_mares},
|
{"Mares", "Quad", DC_FAMILY_MARES_ICONHD , 0x29, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_mares},
|
||||||
{"Mares", "Horizon", DC_FAMILY_MARES_ICONHD , 0x2C, DC_TRANSPORT_SERIAL, NULL},
|
{"Mares", "Horizon", DC_FAMILY_MARES_ICONHD , 0x2C, DC_TRANSPORT_SERIAL, NULL},
|
||||||
{"Mares", "Puck Air 2", DC_FAMILY_MARES_ICONHD , 0x2D, DC_TRANSPORT_BLE, dc_filter_mares},
|
|
||||||
{"Mares", "Sirius", DC_FAMILY_MARES_ICONHD , 0x2F, DC_TRANSPORT_BLE, dc_filter_mares},
|
|
||||||
{"Mares", "Quad Ci", DC_FAMILY_MARES_ICONHD , 0x31, DC_TRANSPORT_BLE, dc_filter_mares},
|
|
||||||
{"Mares", "Puck 4", DC_FAMILY_MARES_ICONHD , 0x35, DC_TRANSPORT_BLE, dc_filter_mares},
|
|
||||||
/* Heinrichs Weikamp */
|
/* Heinrichs Weikamp */
|
||||||
{"Heinrichs Weikamp", "OSTC", DC_FAMILY_HW_OSTC, 0, DC_TRANSPORT_SERIAL, NULL},
|
{"Heinrichs Weikamp", "OSTC", DC_FAMILY_HW_OSTC, 0, DC_TRANSPORT_SERIAL, NULL},
|
||||||
{"Heinrichs Weikamp", "OSTC Mk2", DC_FAMILY_HW_OSTC, 1, DC_TRANSPORT_SERIAL, NULL},
|
{"Heinrichs Weikamp", "OSTC Mk2", DC_FAMILY_HW_OSTC, 1, DC_TRANSPORT_SERIAL, NULL},
|
||||||
@ -364,7 +361,6 @@ static const dc_descriptor_t g_descriptors[] = {
|
|||||||
{"Shearwater", "Peregrine", DC_FAMILY_SHEARWATER_PETREL, 9, DC_TRANSPORT_BLE, dc_filter_shearwater},
|
{"Shearwater", "Peregrine", DC_FAMILY_SHEARWATER_PETREL, 9, DC_TRANSPORT_BLE, dc_filter_shearwater},
|
||||||
{"Shearwater", "Petrel 3", DC_FAMILY_SHEARWATER_PETREL, 10, DC_TRANSPORT_BLE, dc_filter_shearwater},
|
{"Shearwater", "Petrel 3", DC_FAMILY_SHEARWATER_PETREL, 10, DC_TRANSPORT_BLE, dc_filter_shearwater},
|
||||||
{"Shearwater", "Perdix 2", DC_FAMILY_SHEARWATER_PETREL, 11, DC_TRANSPORT_BLE, dc_filter_shearwater},
|
{"Shearwater", "Perdix 2", DC_FAMILY_SHEARWATER_PETREL, 11, DC_TRANSPORT_BLE, dc_filter_shearwater},
|
||||||
{"Shearwater", "Tern", DC_FAMILY_SHEARWATER_PETREL, 12, DC_TRANSPORT_BLE, dc_filter_shearwater},
|
|
||||||
/* Dive Rite NiTek Q */
|
/* Dive Rite NiTek Q */
|
||||||
{"Dive Rite", "NiTek Q", DC_FAMILY_DIVERITE_NITEKQ, 0, DC_TRANSPORT_SERIAL, NULL},
|
{"Dive Rite", "NiTek Q", DC_FAMILY_DIVERITE_NITEKQ, 0, DC_TRANSPORT_SERIAL, NULL},
|
||||||
/* Citizen Hyper Aqualand */
|
/* Citizen Hyper Aqualand */
|
||||||
@ -418,20 +414,6 @@ static const dc_descriptor_t g_descriptors[] = {
|
|||||||
{"Ratio", "iX3M 2021 Pro Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x73, DC_TRANSPORT_SERIAL, NULL},
|
{"Ratio", "iX3M 2021 Pro Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x73, DC_TRANSPORT_SERIAL, NULL},
|
||||||
{"Ratio", "iX3M 2021 Pro Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x74, DC_TRANSPORT_SERIAL, NULL},
|
{"Ratio", "iX3M 2021 Pro Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x74, DC_TRANSPORT_SERIAL, NULL},
|
||||||
{"Ratio", "iX3M 2021 Pro Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x75, DC_TRANSPORT_SERIAL, NULL},
|
{"Ratio", "iX3M 2021 Pro Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x75, DC_TRANSPORT_SERIAL, NULL},
|
||||||
{"Ratio", "iDive 2 Free", DC_FAMILY_DIVESYSTEM_IDIVE, 0x80, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
|
||||||
{"Ratio", "iDive 2 Fancy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x81, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
|
||||||
{"Ratio", "iDive 2 Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x82, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
|
||||||
{"Ratio", "iDive 2 Pro", DC_FAMILY_DIVESYSTEM_IDIVE, 0x83, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
|
||||||
{"Ratio", "iDive 2 Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x84, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
|
||||||
{"Ratio", "iDive 2 Tech", DC_FAMILY_DIVESYSTEM_IDIVE, 0x85, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
|
||||||
{"Ratio", "iDive 2 Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x86, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
|
||||||
{"Ratio", "iX3M 2 GPS Gauge", DC_FAMILY_DIVESYSTEM_IDIVE, 0x90, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
|
||||||
{"Ratio", "iX3M 2 GPS Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x91, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
|
||||||
{"Ratio", "iX3M 2 GPS Pro", DC_FAMILY_DIVESYSTEM_IDIVE, 0x92, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
|
||||||
{"Ratio", "iX3M 2 GPS Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x93, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
|
||||||
{"Ratio", "iX3M 2 GPS Tech", DC_FAMILY_DIVESYSTEM_IDIVE, 0x94, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
|
||||||
{"Ratio", "iX3M 2 GPS Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x95, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
|
||||||
{"Ratio", "ATOM", DC_FAMILY_DIVESYSTEM_IDIVE, 0x96, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
|
||||||
{"Ratio", "iX3M 2 Gauge", DC_FAMILY_DIVESYSTEM_IDIVE, 0x100, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
{"Ratio", "iX3M 2 Gauge", DC_FAMILY_DIVESYSTEM_IDIVE, 0x100, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||||
{"Ratio", "iX3M 2 Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x101, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
{"Ratio", "iX3M 2 Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x101, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||||
{"Ratio", "iX3M 2 Pro", DC_FAMILY_DIVESYSTEM_IDIVE, 0x102, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
{"Ratio", "iX3M 2 Pro", DC_FAMILY_DIVESYSTEM_IDIVE, 0x102, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||||
@ -461,6 +443,7 @@ static const dc_descriptor_t g_descriptors[] = {
|
|||||||
{"Deep Six", "Excursion", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
|
{"Deep Six", "Excursion", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
|
||||||
{"Crest", "CR-4", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
|
{"Crest", "CR-4", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
|
||||||
{"Genesis", "Centauri", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
|
{"Genesis", "Centauri", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
|
||||||
|
{"Tusa", "TC1", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
|
||||||
{"Scorpena", "Alpha", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
|
{"Scorpena", "Alpha", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
|
||||||
/* Seac Screen */
|
/* Seac Screen */
|
||||||
{"Seac", "Screen", DC_FAMILY_SEAC_SCREEN, 0, DC_TRANSPORT_SERIAL, NULL},
|
{"Seac", "Screen", DC_FAMILY_SEAC_SCREEN, 0, DC_TRANSPORT_SERIAL, NULL},
|
||||||
@ -510,15 +493,6 @@ dc_match_usb (const void *key, const void *value)
|
|||||||
return k->vid == v->vid && k->pid == v->pid;
|
return k->vid == v->vid && k->pid == v->pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
dc_match_usbhid (const void *key, const void *value)
|
|
||||||
{
|
|
||||||
const dc_usbhid_desc_t *k = (const dc_usbhid_desc_t *) key;
|
|
||||||
const dc_usbhid_desc_t *v = (const dc_usbhid_desc_t *) value;
|
|
||||||
|
|
||||||
return k->vid == v->vid && k->pid == v->pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dc_match_number_with_prefix (const void *key, const void *value)
|
dc_match_number_with_prefix (const void *key, const void *value)
|
||||||
{
|
{
|
||||||
@ -559,13 +533,16 @@ dc_match_oceanic (const void *key, const void *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dc_filter_internal (const void *key, const void *values, size_t count, size_t size, dc_match_t match)
|
dc_filter_internal (const void *key, const void *values, size_t count, size_t size, dc_match_t match, void *params_dst, const void *params_src, size_t params_size)
|
||||||
{
|
{
|
||||||
if (key == NULL)
|
if (key == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
for (size_t i = 0; i < count; ++i) {
|
for (size_t i = 0; i < count; ++i) {
|
||||||
if (match (key, (const unsigned char *) values + i * size)) {
|
if (match (key, (const unsigned char *) values + i * size)) {
|
||||||
|
if (params_src && params_dst) {
|
||||||
|
memcpy (params_dst, params_src, params_size);
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -580,8 +557,7 @@ static const char * const rfcomm[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int dc_filter_uwatec (dc_transport_t transport, const void *userdata, void *params)
|
||||||
dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
|
||||||
{
|
{
|
||||||
static const char * const irda[] = {
|
static const char * const irda[] = {
|
||||||
"Aladin Smart Com",
|
"Aladin Smart Com",
|
||||||
@ -592,7 +568,7 @@ dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const v
|
|||||||
"UWATEC Galileo",
|
"UWATEC Galileo",
|
||||||
"UWATEC Galileo Sol",
|
"UWATEC Galileo Sol",
|
||||||
};
|
};
|
||||||
static const dc_usbhid_desc_t usbhid[] = {
|
static const dc_usb_desc_t usbhid[] = {
|
||||||
{0x2e6c, 0x3201}, // G2, G2 TEK
|
{0x2e6c, 0x3201}, // G2, G2 TEK
|
||||||
{0x2e6c, 0x3211}, // G2 Console
|
{0x2e6c, 0x3211}, // G2 Console
|
||||||
{0x2e6c, 0x4201}, // G2 HUD
|
{0x2e6c, 0x4201}, // G2 HUD
|
||||||
@ -605,15 +581,12 @@ dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const v
|
|||||||
"A1",
|
"A1",
|
||||||
"A2",
|
"A2",
|
||||||
"G2 TEK",
|
"G2 TEK",
|
||||||
"Galileo 3",
|
|
||||||
"Luna 2.0 AI",
|
|
||||||
"Luna 2.0",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (transport == DC_TRANSPORT_IRDA) {
|
if (transport == DC_TRANSPORT_IRDA) {
|
||||||
return DC_FILTER_INTERNAL (userdata, irda, 0, dc_match_name);
|
return DC_FILTER_INTERNAL (userdata, irda, 0, dc_match_name);
|
||||||
} else if (transport == DC_TRANSPORT_USBHID) {
|
} else if (transport == DC_TRANSPORT_USBHID) {
|
||||||
return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usbhid);
|
return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usb);
|
||||||
} else if (transport == DC_TRANSPORT_BLE) {
|
} else if (transport == DC_TRANSPORT_BLE) {
|
||||||
return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_name);
|
return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_name);
|
||||||
}
|
}
|
||||||
@ -621,10 +594,9 @@ dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const v
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int dc_filter_suunto (dc_transport_t transport, const void *userdata, void *params)
|
||||||
dc_filter_suunto (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
|
||||||
{
|
{
|
||||||
static const dc_usbhid_desc_t usbhid[] = {
|
static const dc_usb_desc_t usbhid[] = {
|
||||||
{0x1493, 0x0030}, // Eon Steel
|
{0x1493, 0x0030}, // Eon Steel
|
||||||
{0x1493, 0x0033}, // Eon Core
|
{0x1493, 0x0033}, // Eon Core
|
||||||
{0x1493, 0x0035}, // D5
|
{0x1493, 0x0035}, // D5
|
||||||
@ -638,7 +610,7 @@ dc_filter_suunto (dc_descriptor_t *descriptor, dc_transport_t transport, const v
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (transport == DC_TRANSPORT_USBHID) {
|
if (transport == DC_TRANSPORT_USBHID) {
|
||||||
return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usbhid);
|
return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usb);
|
||||||
} else if (transport == DC_TRANSPORT_BLE) {
|
} else if (transport == DC_TRANSPORT_BLE) {
|
||||||
return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_prefix);
|
return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_prefix);
|
||||||
}
|
}
|
||||||
@ -646,8 +618,7 @@ dc_filter_suunto (dc_descriptor_t *descriptor, dc_transport_t transport, const v
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int dc_filter_hw (dc_transport_t transport, const void *userdata, void *params)
|
||||||
dc_filter_hw (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
|
||||||
{
|
{
|
||||||
static const char * const bluetooth[] = {
|
static const char * const bluetooth[] = {
|
||||||
"OSTC",
|
"OSTC",
|
||||||
@ -663,8 +634,7 @@ dc_filter_hw (dc_descriptor_t *descriptor, dc_transport_t transport, const void
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int dc_filter_shearwater (dc_transport_t transport, const void *userdata, void *params)
|
||||||
dc_filter_shearwater (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
|
||||||
{
|
{
|
||||||
static const char * const bluetooth[] = {
|
static const char * const bluetooth[] = {
|
||||||
"Predator",
|
"Predator",
|
||||||
@ -676,7 +646,6 @@ dc_filter_shearwater (dc_descriptor_t *descriptor, dc_transport_t transport, con
|
|||||||
"Perdix 2",
|
"Perdix 2",
|
||||||
"Teric",
|
"Teric",
|
||||||
"Peregrine",
|
"Peregrine",
|
||||||
"Tern"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (transport == DC_TRANSPORT_BLUETOOTH || transport == DC_TRANSPORT_BLE) {
|
if (transport == DC_TRANSPORT_BLUETOOTH || transport == DC_TRANSPORT_BLE) {
|
||||||
@ -688,8 +657,7 @@ dc_filter_shearwater (dc_descriptor_t *descriptor, dc_transport_t transport, con
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int dc_filter_tecdiving (dc_transport_t transport, const void *userdata, void *params)
|
||||||
dc_filter_tecdiving (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
|
||||||
{
|
{
|
||||||
static const char * const bluetooth[] = {
|
static const char * const bluetooth[] = {
|
||||||
"DiveComputer",
|
"DiveComputer",
|
||||||
@ -704,15 +672,11 @@ dc_filter_tecdiving (dc_descriptor_t *descriptor, dc_transport_t transport, cons
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int dc_filter_mares (dc_transport_t transport, const void *userdata, void *params)
|
||||||
dc_filter_mares (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
|
||||||
{
|
{
|
||||||
static const char * const bluetooth[] = {
|
static const char * const bluetooth[] = {
|
||||||
"Mares bluelink pro",
|
"Mares bluelink pro",
|
||||||
"Mares Genius",
|
"Mares Genius",
|
||||||
"Sirius",
|
|
||||||
"Quad Ci",
|
|
||||||
"Puck4",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (transport == DC_TRANSPORT_BLE) {
|
if (transport == DC_TRANSPORT_BLE) {
|
||||||
@ -722,13 +686,11 @@ dc_filter_mares (dc_descriptor_t *descriptor, dc_transport_t transport, const vo
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int dc_filter_divesystem (dc_transport_t transport, const void *userdata, void *params)
|
||||||
dc_filter_divesystem (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
|
||||||
{
|
{
|
||||||
static const char * const bluetooth[] = {
|
static const char * const bluetooth[] = {
|
||||||
"DS",
|
"DS",
|
||||||
"IX5M",
|
"IX5M",
|
||||||
"RATIO-",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (transport == DC_TRANSPORT_BLUETOOTH || transport == DC_TRANSPORT_BLE) {
|
if (transport == DC_TRANSPORT_BLUETOOTH || transport == DC_TRANSPORT_BLE) {
|
||||||
@ -738,8 +700,7 @@ dc_filter_divesystem (dc_descriptor_t *descriptor, dc_transport_t transport, con
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int dc_filter_oceanic (dc_transport_t transport, const void *userdata, void *params)
|
||||||
dc_filter_oceanic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
|
||||||
{
|
{
|
||||||
static const unsigned int model[] = {
|
static const unsigned int model[] = {
|
||||||
0x4552, // Oceanic Pro Plus X
|
0x4552, // Oceanic Pro Plus X
|
||||||
@ -753,10 +714,8 @@ dc_filter_oceanic (dc_descriptor_t *descriptor, dc_transport_t transport, const
|
|||||||
0x4654, // Oceanic Veo 4.0
|
0x4654, // Oceanic Veo 4.0
|
||||||
0x4655, // Sherwood Wisdom 4
|
0x4655, // Sherwood Wisdom 4
|
||||||
0x4656, // Oceanic Pro Plus 4
|
0x4656, // Oceanic Pro Plus 4
|
||||||
0x4741, // Apeks DSX
|
|
||||||
0x4742, // Sherwood Beacon
|
0x4742, // Sherwood Beacon
|
||||||
0x4743, // Aqualung i470TC
|
0x4743, // Aqualung i470TC
|
||||||
0x4744, // Aqualung i330R
|
|
||||||
0x4749, // Aqualung i200C
|
0x4749, // Aqualung i200C
|
||||||
0x474B, // Oceanic Geo Air
|
0x474B, // Oceanic Geo Air
|
||||||
};
|
};
|
||||||
@ -768,8 +727,7 @@ dc_filter_oceanic (dc_descriptor_t *descriptor, dc_transport_t transport, const
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int dc_filter_mclean(dc_transport_t transport, const void *userdata, void *params)
|
||||||
dc_filter_mclean(dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
|
||||||
{
|
{
|
||||||
static const char * const bluetooth[] = {
|
static const char * const bluetooth[] = {
|
||||||
"McLean Extreme",
|
"McLean Extreme",
|
||||||
@ -784,27 +742,30 @@ dc_filter_mclean(dc_descriptor_t *descriptor, dc_transport_t transport, const vo
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int dc_filter_atomic (dc_transport_t transport, const void *userdata, void *params)
|
||||||
dc_filter_atomic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
|
||||||
{
|
{
|
||||||
static const dc_usb_desc_t usb[] = {
|
static const dc_usb_desc_t usb[] = {
|
||||||
{0x0471, 0x0888}, // Atomic Aquatics Cobalt
|
{0x0471, 0x0888}, // Atomic Aquatics Cobalt
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const dc_usb_params_t usb_params = {
|
||||||
|
0, 0x82, 0x02
|
||||||
|
};
|
||||||
|
|
||||||
if (transport == DC_TRANSPORT_USB) {
|
if (transport == DC_TRANSPORT_USB) {
|
||||||
return DC_FILTER_INTERNAL (userdata, usb, 0, dc_match_usb);
|
return DC_FILTER_INTERNAL_WITH_PARAMS (userdata, usb, 0, dc_match_usb, params, &usb_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int dc_filter_deepsix (dc_transport_t transport, const void *userdata, void *params)
|
||||||
dc_filter_deepsix (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
|
||||||
{
|
{
|
||||||
static const char * const bluetooth[] = {
|
static const char * const bluetooth[] = {
|
||||||
"EXCURSION",
|
"EXCURSION",
|
||||||
"Crest-CR4",
|
"Crest-CR4",
|
||||||
"CENTAURI",
|
"CENTAURI",
|
||||||
|
"TC1",
|
||||||
"ALPHA",
|
"ALPHA",
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -815,8 +776,7 @@ dc_filter_deepsix (dc_descriptor_t *descriptor, dc_transport_t transport, const
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int dc_filter_deepblu (dc_transport_t transport, const void *userdata, void *params)
|
||||||
dc_filter_deepblu (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
|
||||||
{
|
{
|
||||||
static const char * const bluetooth[] = {
|
static const char * const bluetooth[] = {
|
||||||
"COSMIQ",
|
"COSMIQ",
|
||||||
@ -829,8 +789,7 @@ dc_filter_deepblu (dc_descriptor_t *descriptor, dc_transport_t transport, const
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int dc_filter_oceans (dc_transport_t transport, const void *userdata, void *params)
|
||||||
dc_filter_oceans (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
|
||||||
{
|
{
|
||||||
static const char * const bluetooth[] = {
|
static const char * const bluetooth[] = {
|
||||||
"S1",
|
"S1",
|
||||||
@ -843,8 +802,7 @@ dc_filter_oceans (dc_descriptor_t *descriptor, dc_transport_t transport, const v
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int dc_filter_divesoft (dc_transport_t transport, const void *userdata, void *params)
|
||||||
dc_filter_divesoft (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
|
||||||
{
|
{
|
||||||
static const char * const bluetooth[] = {
|
static const char * const bluetooth[] = {
|
||||||
"Freedom",
|
"Freedom",
|
||||||
@ -950,10 +908,10 @@ dc_descriptor_get_transports (dc_descriptor_t *descriptor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params)
|
||||||
{
|
{
|
||||||
if (descriptor == NULL || descriptor->filter == NULL || userdata == NULL)
|
if (descriptor == NULL || descriptor->filter == NULL || userdata == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return descriptor->filter (descriptor, transport, userdata);
|
return descriptor->filter (transport, userdata, params);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,7 +38,6 @@
|
|||||||
#include "oceanic_atom2.h"
|
#include "oceanic_atom2.h"
|
||||||
#include "oceanic_veo250.h"
|
#include "oceanic_veo250.h"
|
||||||
#include "oceanic_vtpro.h"
|
#include "oceanic_vtpro.h"
|
||||||
#include "pelagic_i330r.h"
|
|
||||||
#include "mares_darwin.h"
|
#include "mares_darwin.h"
|
||||||
#include "mares_iconhd.h"
|
#include "mares_iconhd.h"
|
||||||
#include "mares_nemo.h"
|
#include "mares_nemo.h"
|
||||||
@ -163,9 +162,6 @@ dc_device_open (dc_device_t **out, dc_context_t *context, dc_descriptor_t *descr
|
|||||||
case DC_FAMILY_OCEANIC_ATOM2:
|
case DC_FAMILY_OCEANIC_ATOM2:
|
||||||
rc = oceanic_atom2_device_open (&device, context, iostream, dc_descriptor_get_model (descriptor));
|
rc = oceanic_atom2_device_open (&device, context, iostream, dc_descriptor_get_model (descriptor));
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_PELAGIC_I330R:
|
|
||||||
rc = pelagic_i330r_device_open (&device, context, iostream, dc_descriptor_get_model (descriptor));
|
|
||||||
break;
|
|
||||||
case DC_FAMILY_MARES_NEMO:
|
case DC_FAMILY_MARES_NEMO:
|
||||||
rc = mares_nemo_device_open (&device, context, iostream);
|
rc = mares_nemo_device_open (&device, context, iostream);
|
||||||
break;
|
break;
|
||||||
@ -176,7 +172,7 @@ dc_device_open (dc_device_t **out, dc_context_t *context, dc_descriptor_t *descr
|
|||||||
rc = mares_darwin_device_open (&device, context, iostream, dc_descriptor_get_model (descriptor));
|
rc = mares_darwin_device_open (&device, context, iostream, dc_descriptor_get_model (descriptor));
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_MARES_ICONHD:
|
case DC_FAMILY_MARES_ICONHD:
|
||||||
rc = mares_iconhd_device_open (&device, context, iostream, dc_descriptor_get_model (descriptor));
|
rc = mares_iconhd_device_open (&device, context, iostream);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_HW_OSTC:
|
case DC_FAMILY_HW_OSTC:
|
||||||
rc = hw_ostc_device_open (&device, context, iostream);
|
rc = hw_ostc_device_open (&device, context, iostream);
|
||||||
|
|||||||
@ -35,7 +35,7 @@ dc_status_t
|
|||||||
diverite_nitekq_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
diverite_nitekq_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
diverite_nitekq_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
diverite_nitekq_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,6 +49,7 @@ struct diverite_nitekq_parser_t {
|
|||||||
double maxdepth;
|
double maxdepth;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static dc_status_t diverite_nitekq_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t diverite_nitekq_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t diverite_nitekq_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t diverite_nitekq_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t diverite_nitekq_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t diverite_nitekq_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t diverite_nitekq_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -56,6 +57,7 @@ static dc_status_t diverite_nitekq_parser_samples_foreach (dc_parser_t *abstract
|
|||||||
static const dc_parser_vtable_t diverite_nitekq_parser_vtable = {
|
static const dc_parser_vtable_t diverite_nitekq_parser_vtable = {
|
||||||
sizeof(diverite_nitekq_parser_t),
|
sizeof(diverite_nitekq_parser_t),
|
||||||
DC_FAMILY_DIVERITE_NITEKQ,
|
DC_FAMILY_DIVERITE_NITEKQ,
|
||||||
|
diverite_nitekq_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -67,7 +69,7 @@ static const dc_parser_vtable_t diverite_nitekq_parser_vtable = {
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
diverite_nitekq_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
diverite_nitekq_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||||
{
|
{
|
||||||
diverite_nitekq_parser_t *parser = NULL;
|
diverite_nitekq_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -75,7 +77,7 @@ diverite_nitekq_parser_create (dc_parser_t **out, dc_context_t *context, const u
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (diverite_nitekq_parser_t *) dc_parser_allocate (context, &diverite_nitekq_parser_vtable, data, size);
|
parser = (diverite_nitekq_parser_t *) dc_parser_allocate (context, &diverite_nitekq_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -99,6 +101,13 @@ diverite_nitekq_parser_create (dc_parser_t **out, dc_context_t *context, const u
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
diverite_nitekq_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
diverite_nitekq_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
diverite_nitekq_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -152,7 +161,6 @@ diverite_nitekq_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, u
|
|||||||
*((unsigned int *) value) = parser->ngasmixes;
|
*((unsigned int *) value) = parser->ngasmixes;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
gasmix->helium = parser->he[flags] / 100.0;
|
gasmix->helium = parser->he[flags] / 100.0;
|
||||||
gasmix->oxygen = parser->o2[flags] / 100.0;
|
gasmix->oxygen = parser->o2[flags] / 100.0;
|
||||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||||
@ -256,13 +264,13 @@ diverite_nitekq_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
|
|||||||
|
|
||||||
// Time (seconds).
|
// Time (seconds).
|
||||||
time += interval;
|
time += interval;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Gas change
|
// Gas change
|
||||||
if (gasmix != gasmix_previous) {
|
if (gasmix != gasmix_previous) {
|
||||||
sample.gasmix = gasmix;
|
sample.gasmix = gasmix;
|
||||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
gasmix_previous = gasmix;
|
gasmix_previous = gasmix;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,7 +282,7 @@ diverite_nitekq_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
|
|||||||
sample.depth = depth / 10.0;
|
sample.depth = depth / 10.0;
|
||||||
else
|
else
|
||||||
sample.depth = depth * FEET / 10.0;
|
sample.depth = depth * FEET / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
|
|
||||||
if (type == 3) {
|
if (type == 3) {
|
||||||
@ -285,9 +293,8 @@ diverite_nitekq_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
|
|||||||
if (offset + 1 > size)
|
if (offset + 1 > size)
|
||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
unsigned int ppo2 = data[offset];
|
unsigned int ppo2 = data[offset];
|
||||||
sample.ppo2.sensor = DC_SENSOR_NONE;
|
sample.ppo2 = ppo2 / 100.0;
|
||||||
sample.ppo2.value = ppo2 / 100.0;
|
if (callback) callback (DC_SAMPLE_PPO2, sample, userdata);
|
||||||
if (callback) callback (DC_SAMPLE_PPO2, &sample, userdata);
|
|
||||||
offset++;
|
offset++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -35,7 +35,7 @@ dc_status_t
|
|||||||
divesoft_freedom_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
divesoft_freedom_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
divesoft_freedom_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
divesoft_freedom_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -254,6 +254,7 @@ typedef struct divesoft_freedom_parser_t {
|
|||||||
unsigned int calibrated;
|
unsigned int calibrated;
|
||||||
} divesoft_freedom_parser_t;
|
} divesoft_freedom_parser_t;
|
||||||
|
|
||||||
|
static dc_status_t divesoft_freedom_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t divesoft_freedom_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t divesoft_freedom_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t divesoft_freedom_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t divesoft_freedom_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -261,6 +262,7 @@ static dc_status_t divesoft_freedom_parser_samples_foreach (dc_parser_t *abstrac
|
|||||||
static const dc_parser_vtable_t divesoft_freedom_parser_vtable = {
|
static const dc_parser_vtable_t divesoft_freedom_parser_vtable = {
|
||||||
sizeof(divesoft_freedom_parser_t),
|
sizeof(divesoft_freedom_parser_t),
|
||||||
DC_FAMILY_DIVESOFT_FREEDOM,
|
DC_FAMILY_DIVESOFT_FREEDOM,
|
||||||
|
divesoft_freedom_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -641,7 +643,7 @@ divesoft_freedom_cache (divesoft_freedom_parser_t *parser)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
divesoft_freedom_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
divesoft_freedom_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||||
{
|
{
|
||||||
divesoft_freedom_parser_t *parser = NULL;
|
divesoft_freedom_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -649,7 +651,7 @@ divesoft_freedom_parser_create (dc_parser_t **out, dc_context_t *context, const
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (divesoft_freedom_parser_t *) dc_parser_allocate (context, &divesoft_freedom_parser_vtable, data, size);
|
parser = (divesoft_freedom_parser_t *) dc_parser_allocate (context, &divesoft_freedom_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -696,6 +698,50 @@ divesoft_freedom_parser_create (dc_parser_t **out, dc_context_t *context, const
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
divesoft_freedom_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
divesoft_freedom_parser_t *parser = (divesoft_freedom_parser_t *) abstract;
|
||||||
|
|
||||||
|
// Reset the cache.
|
||||||
|
parser->cached = 0;
|
||||||
|
parser->version = 0;
|
||||||
|
parser->headersize = 0;
|
||||||
|
parser->divetime = 0;
|
||||||
|
parser->divemode = 0;
|
||||||
|
parser->temperature_min = 0;
|
||||||
|
parser->maxdepth = 0;
|
||||||
|
parser->atmospheric = 0;
|
||||||
|
parser->avgdepth = 0;
|
||||||
|
parser->ngasmixes = 0;
|
||||||
|
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||||
|
parser->gasmix[i].oxygen = 0;
|
||||||
|
parser->gasmix[i].helium = 0;
|
||||||
|
parser->gasmix[i].type = 0;
|
||||||
|
parser->gasmix[i].id = 0;
|
||||||
|
}
|
||||||
|
parser->diluent = UNDEFINED;
|
||||||
|
parser->ntanks = 0;
|
||||||
|
for (unsigned int i = 0; i < NTANKS; ++i) {
|
||||||
|
parser->tank[i].volume = 0;
|
||||||
|
parser->tank[i].workpressure = 0;
|
||||||
|
parser->tank[i].beginpressure = 0;
|
||||||
|
parser->tank[i].endpressure = 0;
|
||||||
|
parser->tank[i].transmitter = 0;
|
||||||
|
parser->tank[i].active = 0;
|
||||||
|
}
|
||||||
|
parser->vpm = 0;
|
||||||
|
parser->gf_lo = 0;
|
||||||
|
parser->gf_hi = 0;
|
||||||
|
parser->seawater = 0;
|
||||||
|
for (unsigned int i = 0; i < NSENSORS; ++i) {
|
||||||
|
parser->calibration[i] = 0;
|
||||||
|
}
|
||||||
|
parser->calibrated = 0;
|
||||||
|
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
divesoft_freedom_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
divesoft_freedom_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -709,21 +755,13 @@ divesoft_freedom_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *date
|
|||||||
return status;
|
return status;
|
||||||
|
|
||||||
unsigned int timestamp = array_uint32_le (data + 8);
|
unsigned int timestamp = array_uint32_le (data + 8);
|
||||||
|
dc_ticks_t ticks = (dc_ticks_t) timestamp + EPOCH;
|
||||||
int timezone = 0;
|
|
||||||
if (parser->version == HEADER_SIGNATURE_V2) {
|
|
||||||
timezone = ((signed short) array_uint16_le (data + 40)) * 60;
|
|
||||||
} else {
|
|
||||||
timezone = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dc_ticks_t ticks = (dc_ticks_t) timestamp + EPOCH + timezone;
|
|
||||||
|
|
||||||
if (!dc_datetime_gmtime (datetime, ticks))
|
if (!dc_datetime_gmtime (datetime, ticks))
|
||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
|
|
||||||
if (parser->version == HEADER_SIGNATURE_V2) {
|
if (parser->version == HEADER_SIGNATURE_V2) {
|
||||||
datetime->timezone = timezone;
|
datetime->timezone = ((signed short) array_uint16_le (data + 40)) * 60;
|
||||||
} else {
|
} else {
|
||||||
datetime->timezone = DC_TIMEZONE_NONE;
|
datetime->timezone = DC_TIMEZONE_NONE;
|
||||||
}
|
}
|
||||||
@ -800,13 +838,6 @@ divesoft_freedom_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
|
|||||||
*((unsigned int *) value) = parser->ngasmixes;
|
*((unsigned int *) value) = parser->ngasmixes;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
if (parser->gasmix[flags].type == OXYGEN) {
|
|
||||||
gasmix->usage = DC_USAGE_OXYGEN;
|
|
||||||
} else if (parser->gasmix[flags].type == DILUENT) {
|
|
||||||
gasmix->usage = DC_USAGE_DILUENT;
|
|
||||||
} else {
|
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
}
|
|
||||||
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
||||||
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
||||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||||
@ -828,7 +859,6 @@ divesoft_freedom_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
|
|||||||
tank->beginpressure = parser->tank[flags].beginpressure * 2.0;
|
tank->beginpressure = parser->tank[flags].beginpressure * 2.0;
|
||||||
tank->endpressure = parser->tank[flags].endpressure * 2.0;
|
tank->endpressure = parser->tank[flags].endpressure * 2.0;
|
||||||
tank->gasmix = flags;
|
tank->gasmix = flags;
|
||||||
tank->usage = DC_USAGE_NONE;
|
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_DECOMODEL:
|
case DC_FIELD_DECOMODEL:
|
||||||
if (parser->vpm) {
|
if (parser->vpm) {
|
||||||
@ -894,15 +924,15 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
time = timestamp;
|
time = timestamp;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback(DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_TIME, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initial diluent.
|
// Initial diluent.
|
||||||
if (!initial) {
|
if (!initial) {
|
||||||
if (parser->diluent != UNDEFINED) {
|
if (parser->diluent != UNDEFINED) {
|
||||||
sample.gasmix = parser->diluent;
|
sample.gasmix = parser->diluent;
|
||||||
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
}
|
}
|
||||||
initial = 1;
|
initial = 1;
|
||||||
}
|
}
|
||||||
@ -913,19 +943,18 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
unsigned int ppo2 = array_uint16_le (data + offset + 6);
|
unsigned int ppo2 = array_uint16_le (data + offset + 6);
|
||||||
|
|
||||||
sample.depth = depth / 100.0;
|
sample.depth = depth / 100.0;
|
||||||
if (callback) callback(DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
if (ppo2) {
|
if (ppo2) {
|
||||||
sample.ppo2.sensor = DC_SENSOR_NONE;
|
sample.ppo2 = ppo2 * 10.0 / BAR;
|
||||||
sample.ppo2.value = ppo2 * 10.0 / BAR;
|
if (callback) callback(DC_SAMPLE_PPO2, sample, userdata);
|
||||||
if (callback) callback(DC_SAMPLE_PPO2, &sample, userdata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id == POINT_2) {
|
if (id == POINT_2) {
|
||||||
unsigned int orientation = array_uint32_le (data + offset + 8);
|
unsigned int orientation = array_uint32_le (data + offset + 8);
|
||||||
unsigned int heading = orientation & 0x1FF;
|
unsigned int heading = orientation & 0x1FF;
|
||||||
sample.bearing = heading;
|
sample.bearing = heading;
|
||||||
if (callback) callback (DC_SAMPLE_BEARING, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_BEARING, sample, userdata);
|
||||||
} else if (id == POINT_1 || id == POINT_1_OLD) {
|
} else if (id == POINT_1 || id == POINT_1_OLD) {
|
||||||
unsigned int misc = array_uint32_le (data + offset + 8);
|
unsigned int misc = array_uint32_le (data + offset + 8);
|
||||||
unsigned int ceiling = array_uint16_le (data + offset + 12);
|
unsigned int ceiling = array_uint16_le (data + offset + 12);
|
||||||
@ -936,7 +965,7 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
|
|
||||||
// Temperature
|
// Temperature
|
||||||
sample.temperature = (signed int) signextend (temp, 10) / 10.0;
|
sample.temperature = (signed int) signextend (temp, 10) / 10.0;
|
||||||
if (callback) callback(DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
|
|
||||||
// Deco / NDL
|
// Deco / NDL
|
||||||
if (ceiling) {
|
if (ceiling) {
|
||||||
@ -948,13 +977,12 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
sample.deco.time = ndl * 60;
|
sample.deco.time = ndl * 60;
|
||||||
sample.deco.depth = 0.0;
|
sample.deco.depth = 0.0;
|
||||||
}
|
}
|
||||||
sample.deco.tts = tts * 60;
|
if (callback) callback(DC_SAMPLE_DECO, sample, userdata);
|
||||||
if (callback) callback(DC_SAMPLE_DECO, &sample, userdata);
|
|
||||||
|
|
||||||
// Setpoint
|
// Setpoint
|
||||||
if (setpoint) {
|
if (setpoint) {
|
||||||
sample.setpoint = setpoint / 100.0;
|
sample.setpoint = setpoint / 100.0;
|
||||||
if (callback) callback(DC_SAMPLE_SETPOINT, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_SETPOINT, sample, userdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ((type >= LREC_MANIPULATION && type <= LREC_ACTIVITY) || type == LREC_INFO) {
|
} else if ((type >= LREC_MANIPULATION && type <= LREC_ACTIVITY) || type == LREC_INFO) {
|
||||||
@ -966,7 +994,7 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
sample.event.time = 0;
|
sample.event.time = 0;
|
||||||
sample.event.flags = 0;
|
sample.event.flags = 0;
|
||||||
sample.event.value = 0;
|
sample.event.value = 0;
|
||||||
if (callback) callback(DC_SAMPLE_EVENT, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_EVENT, sample, userdata);
|
||||||
} else if (event == EVENT_MIX_CHANGED || event == EVENT_DILUENT || event == EVENT_CHANGE_MODE) {
|
} else if (event == EVENT_MIX_CHANGED || event == EVENT_DILUENT || event == EVENT_CHANGE_MODE) {
|
||||||
unsigned int o2 = data[offset + 6];
|
unsigned int o2 = data[offset + 6];
|
||||||
unsigned int he = data[offset + 7];
|
unsigned int he = data[offset + 7];
|
||||||
@ -986,13 +1014,13 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
}
|
}
|
||||||
sample.gasmix = idx;
|
sample.gasmix = idx;
|
||||||
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
} else if (event == EVENT_CNS) {
|
} else if (event == EVENT_CNS) {
|
||||||
sample.cns = array_uint16_le (data + offset + 6) / 100.0;
|
sample.cns = array_uint16_le (data + offset + 6) / 100.0;
|
||||||
if (callback) callback(DC_SAMPLE_CNS, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_CNS, sample, userdata);
|
||||||
} else if (event == EVENT_SETPOINT_MANUAL || event == EVENT_SETPOINT_AUTO) {
|
} else if (event == EVENT_SETPOINT_MANUAL || event == EVENT_SETPOINT_AUTO) {
|
||||||
sample.setpoint = data[6] / 100.0;
|
sample.setpoint = data[6] / 100.0;
|
||||||
if (callback) callback(DC_SAMPLE_SETPOINT, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_SETPOINT, sample, userdata);
|
||||||
}
|
}
|
||||||
} else if (type == LREC_MEASURE) {
|
} else if (type == LREC_MEASURE) {
|
||||||
// Measurement record.
|
// Measurement record.
|
||||||
@ -1010,27 +1038,25 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
|
|
||||||
sample.pressure.tank = idx;
|
sample.pressure.tank = idx;
|
||||||
sample.pressure.value = pressure * 2.0;
|
sample.pressure.value = pressure * 2.0;
|
||||||
if (callback) callback(DC_SAMPLE_PRESSURE, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_PRESSURE, sample, userdata);
|
||||||
}
|
}
|
||||||
} else if (id == MEASURE_ID_OXYGEN) {
|
} else if (id == MEASURE_ID_OXYGEN) {
|
||||||
for (unsigned int i = 0; i < NSENSORS; ++i) {
|
for (unsigned int i = 0; i < NSENSORS; ++i) {
|
||||||
unsigned int ppo2 = array_uint16_le (data + offset + 4 + i * 2);
|
unsigned int ppo2 = array_uint16_le (data + offset + 4 + i * 2);
|
||||||
if (ppo2 == 0 || ppo2 == 0xFFFF)
|
if (ppo2 == 0 || ppo2 == 0xFFFF)
|
||||||
continue;
|
continue;
|
||||||
sample.ppo2.sensor = i;
|
sample.ppo2 = ppo2 * 10.0 / BAR;
|
||||||
sample.ppo2.value = ppo2 * 10.0 / BAR;
|
if (callback) callback(DC_SAMPLE_PPO2, sample, userdata);
|
||||||
if (callback) callback(DC_SAMPLE_PPO2, &sample, userdata);
|
|
||||||
}
|
}
|
||||||
} else if (id == MEASURE_ID_OXYGEN_MV) {
|
} else if (id == MEASURE_ID_OXYGEN_MV) {
|
||||||
for (unsigned int i = 0; i < NSENSORS; ++i) {
|
for (unsigned int i = 0; i < NSENSORS; ++i) {
|
||||||
unsigned int value = array_uint16_le (data + offset + 4 + i * 2);
|
unsigned int value = array_uint16_le (data + offset + 4 + i * 2);
|
||||||
unsigned int state = data[offset + 12 + i];
|
unsigned int state = data[offset + 12 + i];
|
||||||
if (!parser->calibrated || parser->calibration[i] == 0 ||
|
if (!parser->calibrated || state == SENSTAT_UNCALIBRATED ||
|
||||||
state == SENSTAT_UNCALIBRATED || state == SENSTAT_NOT_EXIST)
|
state == SENSTAT_NOT_EXIST)
|
||||||
continue;
|
continue;
|
||||||
sample.ppo2.sensor = i;
|
sample.ppo2 = value / 100.0 * parser->calibration[i] / BAR;
|
||||||
sample.ppo2.value = value / 100.0 * parser->calibration[i] / BAR;
|
if (callback) callback(DC_SAMPLE_PPO2, sample, userdata);
|
||||||
if (callback) callback(DC_SAMPLE_PPO2, &sample, userdata);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (type == LREC_STATE) {
|
} else if (type == LREC_STATE) {
|
||||||
|
|||||||
@ -36,7 +36,7 @@ dc_status_t
|
|||||||
divesystem_idive_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
divesystem_idive_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
divesystem_idive_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
divesystem_idive_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,9 +58,6 @@
|
|||||||
#define IX3M2_ZHL16C 2
|
#define IX3M2_ZHL16C 2
|
||||||
#define IX3M2_VPM 3
|
#define IX3M2_VPM 3
|
||||||
|
|
||||||
#define REC_SAMPLE 0
|
|
||||||
#define REC_INFO 1
|
|
||||||
|
|
||||||
typedef struct divesystem_idive_parser_t divesystem_idive_parser_t;
|
typedef struct divesystem_idive_parser_t divesystem_idive_parser_t;
|
||||||
|
|
||||||
typedef struct divesystem_idive_gasmix_t {
|
typedef struct divesystem_idive_gasmix_t {
|
||||||
@ -92,6 +89,7 @@ struct divesystem_idive_parser_t {
|
|||||||
unsigned int gf_high;
|
unsigned int gf_high;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static dc_status_t divesystem_idive_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t divesystem_idive_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t divesystem_idive_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t divesystem_idive_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t divesystem_idive_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -99,6 +97,7 @@ static dc_status_t divesystem_idive_parser_samples_foreach (dc_parser_t *abstrac
|
|||||||
static const dc_parser_vtable_t divesystem_idive_parser_vtable = {
|
static const dc_parser_vtable_t divesystem_idive_parser_vtable = {
|
||||||
sizeof(divesystem_idive_parser_t),
|
sizeof(divesystem_idive_parser_t),
|
||||||
DC_FAMILY_DIVESYSTEM_IDIVE,
|
DC_FAMILY_DIVESYSTEM_IDIVE,
|
||||||
|
divesystem_idive_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -110,7 +109,7 @@ static const dc_parser_vtable_t divesystem_idive_parser_vtable = {
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||||
{
|
{
|
||||||
divesystem_idive_parser_t *parser = NULL;
|
divesystem_idive_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -118,7 +117,7 @@ divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, const
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (divesystem_idive_parser_t *) dc_parser_allocate (context, &divesystem_idive_parser_vtable, data, size);
|
parser = (divesystem_idive_parser_t *) dc_parser_allocate (context, &divesystem_idive_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -157,6 +156,35 @@ divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
divesystem_idive_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
divesystem_idive_parser_t *parser = (divesystem_idive_parser_t *) abstract;
|
||||||
|
|
||||||
|
// Reset the cache.
|
||||||
|
parser->cached = 0;
|
||||||
|
parser->divemode = INVALID;
|
||||||
|
parser->divetime = 0;
|
||||||
|
parser->maxdepth = 0;
|
||||||
|
parser->ngasmixes = 0;
|
||||||
|
parser->ntanks = 0;
|
||||||
|
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||||
|
parser->gasmix[i].oxygen = 0;
|
||||||
|
parser->gasmix[i].helium = 0;
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i < NTANKS; ++i) {
|
||||||
|
parser->tank[i].id = 0;
|
||||||
|
parser->tank[i].beginpressure = 0;
|
||||||
|
parser->tank[i].endpressure = 0;
|
||||||
|
}
|
||||||
|
parser->algorithm = INVALID;
|
||||||
|
parser->gf_low = INVALID;
|
||||||
|
parser->gf_high = INVALID;
|
||||||
|
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
divesystem_idive_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
divesystem_idive_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -289,7 +317,6 @@ divesystem_idive_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
|
|||||||
*((unsigned int *) value) = parser->ngasmixes;
|
*((unsigned int *) value) = parser->ngasmixes;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
||||||
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
||||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||||
@ -304,7 +331,6 @@ divesystem_idive_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
|
|||||||
tank->beginpressure = parser->tank[flags].beginpressure;
|
tank->beginpressure = parser->tank[flags].beginpressure;
|
||||||
tank->endpressure = parser->tank[flags].endpressure;
|
tank->endpressure = parser->tank[flags].endpressure;
|
||||||
tank->gasmix = DC_GASMIX_UNKNOWN;
|
tank->gasmix = DC_GASMIX_UNKNOWN;
|
||||||
tank->usage = DC_USAGE_NONE;
|
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_ATMOSPHERIC:
|
case DC_FIELD_ATMOSPHERIC:
|
||||||
if (ISIX3M(parser->model)) {
|
if (ISIX3M(parser->model)) {
|
||||||
@ -413,7 +439,6 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
unsigned int algorithm_previous = INVALID;
|
unsigned int algorithm_previous = INVALID;
|
||||||
unsigned int gf_low = INVALID;
|
unsigned int gf_low = INVALID;
|
||||||
unsigned int gf_high = INVALID;
|
unsigned int gf_high = INVALID;
|
||||||
unsigned int have_bearing = 0;
|
|
||||||
|
|
||||||
unsigned int firmware = 0;
|
unsigned int firmware = 0;
|
||||||
unsigned int apos4 = 0;
|
unsigned int apos4 = 0;
|
||||||
@ -442,37 +467,27 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
while (offset + samplesize <= size) {
|
while (offset + samplesize <= size) {
|
||||||
dc_sample_value_t sample = {0};
|
dc_sample_value_t sample = {0};
|
||||||
|
|
||||||
// Get the record type.
|
|
||||||
unsigned int type = ISIX3M(parser->model) ?
|
|
||||||
array_uint16_le (data + offset + 52) :
|
|
||||||
REC_SAMPLE;
|
|
||||||
if (type != REC_SAMPLE) {
|
|
||||||
// Skip non-sample records.
|
|
||||||
offset += samplesize;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Time (seconds).
|
// Time (seconds).
|
||||||
unsigned int timestamp = array_uint32_le (data + offset + 2);
|
unsigned int timestamp = array_uint32_le (data + offset + 2);
|
||||||
if (timestamp <= time && time != 0) {
|
if (timestamp <= time) {
|
||||||
ERROR (abstract->context, "Timestamp moved backwards (%u %u).", timestamp, time);
|
ERROR (abstract->context, "Timestamp moved backwards.");
|
||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
}
|
}
|
||||||
time = timestamp;
|
time = timestamp;
|
||||||
sample.time = timestamp * 1000;
|
sample.time = timestamp;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Depth (1/10 m).
|
// Depth (1/10 m).
|
||||||
unsigned int depth = array_uint16_le (data + offset + 6);
|
unsigned int depth = array_uint16_le (data + offset + 6);
|
||||||
if (maxdepth < depth)
|
if (maxdepth < depth)
|
||||||
maxdepth = depth;
|
maxdepth = depth;
|
||||||
sample.depth = depth / 10.0;
|
sample.depth = depth / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
// Temperature (Celsius).
|
// Temperature (Celsius).
|
||||||
signed int temperature = (signed short) array_uint16_le (data + offset + 8);
|
signed int temperature = (signed short) array_uint16_le (data + offset + 8);
|
||||||
sample.temperature = temperature / 10.0;
|
sample.temperature = temperature / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
|
|
||||||
// Dive mode
|
// Dive mode
|
||||||
unsigned int mode = data[offset + 18];
|
unsigned int mode = data[offset + 18];
|
||||||
@ -506,7 +521,7 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
if (mode == SCR || mode == CCR) {
|
if (mode == SCR || mode == CCR) {
|
||||||
unsigned int setpoint = array_uint16_le (data + offset + 19);
|
unsigned int setpoint = array_uint16_le (data + offset + 19);
|
||||||
sample.setpoint = setpoint / 1000.0;
|
sample.setpoint = setpoint / 1000.0;
|
||||||
if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gaschange.
|
// Gaschange.
|
||||||
@ -533,7 +548,7 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
}
|
}
|
||||||
|
|
||||||
sample.gasmix = i;
|
sample.gasmix = i;
|
||||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
o2_previous = o2;
|
o2_previous = o2;
|
||||||
he_previous = he;
|
he_previous = he;
|
||||||
}
|
}
|
||||||
@ -551,20 +566,18 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
if (decostop) {
|
if (decostop) {
|
||||||
sample.deco.type = DC_DECO_DECOSTOP;
|
sample.deco.type = DC_DECO_DECOSTOP;
|
||||||
sample.deco.depth = decostop / 10.0;
|
sample.deco.depth = decostop / 10.0;
|
||||||
sample.deco.time = decotime;
|
sample.deco.time = apos4 ? decotime : tts;
|
||||||
sample.deco.tts = tts;
|
|
||||||
} else {
|
} else {
|
||||||
sample.deco.type = DC_DECO_NDL;
|
sample.deco.type = DC_DECO_NDL;
|
||||||
sample.deco.depth = 0.0;
|
sample.deco.depth = 0.0;
|
||||||
sample.deco.time = tts;
|
sample.deco.time = tts;
|
||||||
sample.deco.tts = 0;
|
|
||||||
}
|
}
|
||||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||||
|
|
||||||
// CNS
|
// CNS
|
||||||
unsigned int cns = array_uint16_le (data + offset + 29);
|
unsigned int cns = array_uint16_le (data + offset + 29);
|
||||||
sample.cns = cns / 100.0;
|
sample.cns = cns / 100.0;
|
||||||
if (callback) callback (DC_SAMPLE_CNS, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
|
||||||
|
|
||||||
// Tank Pressure
|
// Tank Pressure
|
||||||
if (samplesize == SZ_SAMPLE_IX3M_APOS4) {
|
if (samplesize == SZ_SAMPLE_IX3M_APOS4) {
|
||||||
@ -585,7 +598,7 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
sample.event.time = 0;
|
sample.event.time = 0;
|
||||||
sample.event.flags = 0;
|
sample.event.flags = 0;
|
||||||
sample.event.value = 0;
|
sample.event.value = 0;
|
||||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||||
} else {
|
} else {
|
||||||
// Get the index of the tank.
|
// Get the index of the tank.
|
||||||
if (id != tank_previous) {
|
if (id != tank_previous) {
|
||||||
@ -615,20 +628,10 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
if (tank_idx < ntanks) {
|
if (tank_idx < ntanks) {
|
||||||
sample.pressure.tank = tank_idx;
|
sample.pressure.tank = tank_idx;
|
||||||
sample.pressure.value = pressure;
|
sample.pressure.value = pressure;
|
||||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||||
tank[tank_idx].endpressure = pressure;
|
tank[tank_idx].endpressure = pressure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compass bearing
|
|
||||||
unsigned int bearing = array_uint16_le (data + offset + 50);
|
|
||||||
if (bearing != 0) {
|
|
||||||
have_bearing = 1; // Stop ignoring zero values.
|
|
||||||
}
|
|
||||||
if (have_bearing && bearing != 0xFFFF) {
|
|
||||||
sample.bearing = bearing;
|
|
||||||
if (callback) callback (DC_SAMPLE_BEARING, &sample, userdata);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += samplesize;
|
offset += samplesize;
|
||||||
|
|||||||
@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
#define RB_PROFILE_BEGIN 0x000000
|
#define RB_PROFILE_BEGIN 0x000000
|
||||||
#define RB_PROFILE_END 0x200000
|
#define RB_PROFILE_END 0x200000
|
||||||
#define RB_PROFILE_DISTANCE(a,b) ringbuffer_distance (a, b, DC_RINGBUFFER_EMPTY, RB_PROFILE_BEGIN, RB_PROFILE_END)
|
#define RB_PROFILE_DISTANCE(a,b) ringbuffer_distance (a, b, 0, RB_PROFILE_BEGIN, RB_PROFILE_END)
|
||||||
|
|
||||||
#define READY 0x4D
|
#define READY 0x4D
|
||||||
#define HEADER 0x61
|
#define HEADER 0x61
|
||||||
|
|||||||
@ -36,7 +36,7 @@ dc_status_t
|
|||||||
hw_ostc_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
hw_ostc_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
hw_ostc_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
hw_ostc_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1715,10 +1715,6 @@ hw_ostc3_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device->hardware == OSTC4) {
|
|
||||||
return DC_STATUS_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit a device info event.
|
// Emit a device info event.
|
||||||
dc_event_devinfo_t devinfo;
|
dc_event_devinfo_t devinfo;
|
||||||
devinfo.firmware = device->firmware;
|
devinfo.firmware = device->firmware;
|
||||||
|
|||||||
@ -36,7 +36,7 @@ dc_status_t
|
|||||||
hw_ostc3_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
hw_ostc3_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
hw_ostc3_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
hw_ostc3_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,6 +37,10 @@
|
|||||||
|
|
||||||
#define UNDEFINED 0xFFFFFFFF
|
#define UNDEFINED 0xFFFFFFFF
|
||||||
|
|
||||||
|
#define ALL 0
|
||||||
|
#define FIXED 1
|
||||||
|
#define MANUAL 2
|
||||||
|
|
||||||
#define HEADER 1
|
#define HEADER 1
|
||||||
#define PROFILE 2
|
#define PROFILE 2
|
||||||
|
|
||||||
@ -104,12 +108,10 @@ typedef struct hw_ostc_layout_t {
|
|||||||
} hw_ostc_layout_t;
|
} hw_ostc_layout_t;
|
||||||
|
|
||||||
typedef struct hw_ostc_gasmix_t {
|
typedef struct hw_ostc_gasmix_t {
|
||||||
unsigned int id;
|
|
||||||
unsigned int oxygen;
|
unsigned int oxygen;
|
||||||
unsigned int helium;
|
unsigned int helium;
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
unsigned int enabled;
|
unsigned int enabled;
|
||||||
unsigned int active;
|
|
||||||
unsigned int diluent;
|
unsigned int diluent;
|
||||||
} hw_ostc_gasmix_t;
|
} hw_ostc_gasmix_t;
|
||||||
|
|
||||||
@ -124,22 +126,21 @@ typedef struct hw_ostc_parser_t {
|
|||||||
const hw_ostc_layout_t *layout;
|
const hw_ostc_layout_t *layout;
|
||||||
unsigned int ngasmixes;
|
unsigned int ngasmixes;
|
||||||
unsigned int nfixed;
|
unsigned int nfixed;
|
||||||
unsigned int ndisabled;
|
|
||||||
unsigned int initial;
|
unsigned int initial;
|
||||||
unsigned int initial_setpoint;
|
unsigned int initial_setpoint;
|
||||||
unsigned int initial_cns;
|
unsigned int initial_cns;
|
||||||
hw_ostc_gasmix_t gasmix[NGASMIXES];
|
hw_ostc_gasmix_t gasmix[NGASMIXES];
|
||||||
} hw_ostc_parser_t;
|
} hw_ostc_parser_t;
|
||||||
|
|
||||||
|
static dc_status_t hw_ostc_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t hw_ostc_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t hw_ostc_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
|
|
||||||
static dc_status_t hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t callback, void *userdata);
|
|
||||||
|
|
||||||
static const dc_parser_vtable_t hw_ostc_parser_vtable = {
|
static const dc_parser_vtable_t hw_ostc_parser_vtable = {
|
||||||
sizeof(hw_ostc_parser_t),
|
sizeof(hw_ostc_parser_t),
|
||||||
DC_FAMILY_HW_OSTC,
|
DC_FAMILY_HW_OSTC,
|
||||||
|
hw_ostc_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -195,10 +196,15 @@ static const hw_ostc_layout_t hw_ostc_layout_ostc3 = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
hw_ostc_find_gasmix_manual (hw_ostc_parser_t *parser, unsigned int o2, unsigned int he, unsigned int dil)
|
hw_ostc_find_gasmix (hw_ostc_parser_t *parser, unsigned int o2, unsigned int he, unsigned int dil, unsigned int type)
|
||||||
{
|
{
|
||||||
unsigned int offset = parser->nfixed - parser->ndisabled;
|
unsigned int offset = 0;
|
||||||
unsigned int count = parser->ngasmixes;
|
unsigned int count = parser->ngasmixes;
|
||||||
|
if (type == FIXED) {
|
||||||
|
count = parser->nfixed;
|
||||||
|
} else if (type == MANUAL) {
|
||||||
|
offset = parser->nfixed;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int i = offset;
|
unsigned int i = offset;
|
||||||
while (i < count) {
|
while (i < count) {
|
||||||
@ -210,22 +216,6 @@ hw_ostc_find_gasmix_manual (hw_ostc_parser_t *parser, unsigned int o2, unsigned
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int
|
|
||||||
hw_ostc_find_gasmix_fixed (hw_ostc_parser_t *parser, unsigned int id)
|
|
||||||
{
|
|
||||||
unsigned int offset = 0;
|
|
||||||
unsigned int count = parser->nfixed - parser->ndisabled;
|
|
||||||
|
|
||||||
unsigned int i = offset;
|
|
||||||
while (i < count) {
|
|
||||||
if (id == parser->gasmix[i].id)
|
|
||||||
break;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
hw_ostc_is_ccr (unsigned int divemode, unsigned int version)
|
hw_ostc_is_ccr (unsigned int divemode, unsigned int version)
|
||||||
{
|
{
|
||||||
@ -307,23 +297,19 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
|
|||||||
initial = data[31];
|
initial = data[31];
|
||||||
}
|
}
|
||||||
for (unsigned int i = 0; i < ngasmixes; ++i) {
|
for (unsigned int i = 0; i < ngasmixes; ++i) {
|
||||||
gasmix[i].id = i + 1;
|
|
||||||
gasmix[i].oxygen = data[25 + 2 * i];
|
gasmix[i].oxygen = data[25 + 2 * i];
|
||||||
gasmix[i].helium = 0;
|
gasmix[i].helium = 0;
|
||||||
gasmix[i].type = 0;
|
gasmix[i].type = 0;
|
||||||
gasmix[i].enabled = 1;
|
gasmix[i].enabled = 1;
|
||||||
gasmix[i].active = 0;
|
|
||||||
gasmix[i].diluent = 0;
|
gasmix[i].diluent = 0;
|
||||||
}
|
}
|
||||||
} else if (version == 0x23 || version == 0x24) {
|
} else if (version == 0x23 || version == 0x24) {
|
||||||
ngasmixes = 5;
|
ngasmixes = 5;
|
||||||
for (unsigned int i = 0; i < ngasmixes; ++i) {
|
for (unsigned int i = 0; i < ngasmixes; ++i) {
|
||||||
gasmix[i].id = i + 1;
|
|
||||||
gasmix[i].oxygen = data[28 + 4 * i + 0];
|
gasmix[i].oxygen = data[28 + 4 * i + 0];
|
||||||
gasmix[i].helium = data[28 + 4 * i + 1];
|
gasmix[i].helium = data[28 + 4 * i + 1];
|
||||||
gasmix[i].type = data[28 + 4 * i + 3];
|
gasmix[i].type = data[28 + 4 * i + 3];
|
||||||
gasmix[i].enabled = gasmix[i].type != 0;
|
gasmix[i].enabled = gasmix[i].type != 0;
|
||||||
gasmix[i].active = 0;
|
|
||||||
gasmix[i].diluent = ccr;
|
gasmix[i].diluent = ccr;
|
||||||
// Find the first gas marked as the initial gas.
|
// Find the first gas marked as the initial gas.
|
||||||
if (initial == UNDEFINED && data[28 + 4 * i + 3] == 1) {
|
if (initial == UNDEFINED && data[28 + 4 * i + 3] == 1) {
|
||||||
@ -342,7 +328,6 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
|
|||||||
initial = data[31];
|
initial = data[31];
|
||||||
}
|
}
|
||||||
for (unsigned int i = 0; i < ngasmixes; ++i) {
|
for (unsigned int i = 0; i < ngasmixes; ++i) {
|
||||||
gasmix[i].id = i + 1;
|
|
||||||
gasmix[i].oxygen = data[19 + 2 * i + 0];
|
gasmix[i].oxygen = data[19 + 2 * i + 0];
|
||||||
gasmix[i].helium = data[19 + 2 * i + 1];
|
gasmix[i].helium = data[19 + 2 * i + 1];
|
||||||
gasmix[i].type = 0;
|
gasmix[i].type = 0;
|
||||||
@ -351,7 +336,6 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
|
|||||||
} else {
|
} else {
|
||||||
gasmix[i].enabled = 1;
|
gasmix[i].enabled = 1;
|
||||||
}
|
}
|
||||||
gasmix[i].active = 0;
|
|
||||||
gasmix[i].diluent = ccr;
|
gasmix[i].diluent = ccr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -360,6 +344,7 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
|
|||||||
ERROR(abstract->context, "Invalid initial gas mix.");
|
ERROR(abstract->context, "Invalid initial gas mix.");
|
||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
}
|
}
|
||||||
|
initial--; /* Convert to a zero based index. */
|
||||||
} else {
|
} else {
|
||||||
WARNING(abstract->context, "No initial gas mix available.");
|
WARNING(abstract->context, "No initial gas mix available.");
|
||||||
}
|
}
|
||||||
@ -370,7 +355,6 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
|
|||||||
parser->layout = layout;
|
parser->layout = layout;
|
||||||
parser->ngasmixes = ngasmixes;
|
parser->ngasmixes = ngasmixes;
|
||||||
parser->nfixed = ngasmixes;
|
parser->nfixed = ngasmixes;
|
||||||
parser->ndisabled = 0;
|
|
||||||
parser->initial = initial;
|
parser->initial = initial;
|
||||||
parser->initial_setpoint = initial_setpoint;
|
parser->initial_setpoint = initial_setpoint;
|
||||||
parser->initial_cns = initial_cns;
|
parser->initial_cns = initial_cns;
|
||||||
@ -383,7 +367,7 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int hwos, unsigned int model)
|
hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, unsigned int hwos, unsigned int model)
|
||||||
{
|
{
|
||||||
hw_ostc_parser_t *parser = NULL;
|
hw_ostc_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -391,7 +375,7 @@ hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, const
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (hw_ostc_parser_t *) dc_parser_allocate (context, &hw_ostc_parser_vtable, data, size);
|
parser = (hw_ostc_parser_t *) dc_parser_allocate (context, &hw_ostc_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -406,17 +390,14 @@ hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, const
|
|||||||
parser->layout = NULL;
|
parser->layout = NULL;
|
||||||
parser->ngasmixes = 0;
|
parser->ngasmixes = 0;
|
||||||
parser->nfixed = 0;
|
parser->nfixed = 0;
|
||||||
parser->ndisabled = 0;
|
|
||||||
parser->initial = 0;
|
parser->initial = 0;
|
||||||
parser->initial_setpoint = 0;
|
parser->initial_setpoint = 0;
|
||||||
parser->initial_cns = 0;
|
parser->initial_cns = 0;
|
||||||
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||||
parser->gasmix[i].id = 0;
|
|
||||||
parser->gasmix[i].oxygen = 0;
|
parser->gasmix[i].oxygen = 0;
|
||||||
parser->gasmix[i].helium = 0;
|
parser->gasmix[i].helium = 0;
|
||||||
parser->gasmix[i].type = 0;
|
parser->gasmix[i].type = 0;
|
||||||
parser->gasmix[i].enabled = 0;
|
parser->gasmix[i].enabled = 0;
|
||||||
parser->gasmix[i].active = 0;
|
|
||||||
parser->gasmix[i].diluent = 0;
|
parser->gasmix[i].diluent = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,17 +408,44 @@ hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, const
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
hw_ostc_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
hw_ostc_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||||
{
|
{
|
||||||
return hw_ostc_parser_create_internal (out, context, data, size, 0, 0);
|
return hw_ostc_parser_create_internal (out, context, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
hw_ostc3_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
hw_ostc3_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||||
{
|
{
|
||||||
return hw_ostc_parser_create_internal (out, context, data, size, 1, model);
|
return hw_ostc_parser_create_internal (out, context, 1, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
hw_ostc_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
hw_ostc_parser_t *parser = (hw_ostc_parser_t *) abstract;
|
||||||
|
|
||||||
|
// Reset the cache.
|
||||||
|
parser->cached = 0;
|
||||||
|
parser->version = 0;
|
||||||
|
parser->header = 0;
|
||||||
|
parser->layout = NULL;
|
||||||
|
parser->ngasmixes = 0;
|
||||||
|
parser->nfixed = 0;
|
||||||
|
parser->initial = 0;
|
||||||
|
parser->initial_setpoint = 0;
|
||||||
|
parser->initial_cns = 0;
|
||||||
|
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||||
|
parser->gasmix[i].oxygen = 0;
|
||||||
|
parser->gasmix[i].helium = 0;
|
||||||
|
parser->gasmix[i].type = 0;
|
||||||
|
parser->gasmix[i].enabled = 0;
|
||||||
|
parser->gasmix[i].diluent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
hw_ostc_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
hw_ostc_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -511,7 +519,7 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
|
|||||||
|
|
||||||
// Cache the profile data.
|
// Cache the profile data.
|
||||||
if (parser->cached < PROFILE) {
|
if (parser->cached < PROFILE) {
|
||||||
rc = hw_ostc_parser_internal_foreach (parser, NULL, NULL);
|
rc = hw_ostc_parser_samples_foreach (abstract, NULL, NULL);
|
||||||
if (rc != DC_STATUS_SUCCESS)
|
if (rc != DC_STATUS_SUCCESS)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -544,8 +552,6 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
|
|||||||
*((unsigned int *) value) = parser->ngasmixes;
|
*((unsigned int *) value) = parser->ngasmixes;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
gasmix->usage = parser->gasmix[flags].diluent ?
|
|
||||||
DC_USAGE_DILUENT : DC_USAGE_NONE;
|
|
||||||
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
||||||
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
||||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||||
@ -699,12 +705,17 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
|
|||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t callback, void *userdata)
|
hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
|
||||||
{
|
{
|
||||||
dc_parser_t *abstract = (dc_parser_t *) parser;
|
hw_ostc_parser_t *parser = (hw_ostc_parser_t *) abstract;
|
||||||
const unsigned char *data = abstract->data;
|
const unsigned char *data = abstract->data;
|
||||||
unsigned int size = abstract->size;
|
unsigned int size = abstract->size;
|
||||||
|
|
||||||
|
// Cache the parser data.
|
||||||
|
dc_status_t rc = hw_ostc_parser_cache (parser);
|
||||||
|
if (rc != DC_STATUS_SUCCESS)
|
||||||
|
return rc;
|
||||||
|
|
||||||
unsigned int version = parser->version;
|
unsigned int version = parser->version;
|
||||||
unsigned int header = parser->header;
|
unsigned int header = parser->header;
|
||||||
const hw_ostc_layout_t *layout = parser->layout;
|
const hw_ostc_layout_t *layout = parser->layout;
|
||||||
@ -810,7 +821,7 @@ hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t
|
|||||||
|
|
||||||
unsigned int time = 0;
|
unsigned int time = 0;
|
||||||
unsigned int nsamples = 0;
|
unsigned int nsamples = 0;
|
||||||
unsigned int tank = parser->initial != UNDEFINED ? parser->initial - 1 : 0;
|
unsigned int tank = parser->initial != UNDEFINED ? parser->initial : 0;
|
||||||
|
|
||||||
unsigned int offset = header;
|
unsigned int offset = header;
|
||||||
if (version == 0x23 || version == 0x24)
|
if (version == 0x23 || version == 0x24)
|
||||||
@ -822,33 +833,31 @@ hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t
|
|||||||
|
|
||||||
// Time (seconds).
|
// Time (seconds).
|
||||||
time += samplerate;
|
time += samplerate;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Initial gas mix.
|
// Initial gas mix.
|
||||||
if (time == samplerate && parser->initial != UNDEFINED) {
|
if (time == samplerate && parser->initial != UNDEFINED) {
|
||||||
unsigned int idx = hw_ostc_find_gasmix_fixed (parser, parser->initial);
|
sample.gasmix = parser->initial;
|
||||||
parser->gasmix[idx].active = 1;
|
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
sample.gasmix = idx;
|
|
||||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initial setpoint (mbar).
|
// Initial setpoint (mbar).
|
||||||
if (time == samplerate && parser->initial_setpoint != UNDEFINED) {
|
if (time == samplerate && parser->initial_setpoint != UNDEFINED) {
|
||||||
sample.setpoint = parser->initial_setpoint / 100.0;
|
sample.setpoint = parser->initial_setpoint / 100.0;
|
||||||
if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initial CNS (%).
|
// Initial CNS (%).
|
||||||
if (time == samplerate && parser->initial_cns != UNDEFINED) {
|
if (time == samplerate && parser->initial_cns != UNDEFINED) {
|
||||||
sample.cns = parser->initial_cns / 100.0;
|
sample.cns = parser->initial_cns / 100.0;
|
||||||
if (callback) callback (DC_SAMPLE_CNS, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Depth (1/100 m).
|
// Depth (1/100 m).
|
||||||
unsigned int depth = array_uint16_le (data + offset);
|
unsigned int depth = array_uint16_le (data + offset);
|
||||||
sample.depth = depth / 100.0;
|
sample.depth = depth / 100.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
|
|
||||||
// Extended sample info.
|
// Extended sample info.
|
||||||
@ -907,7 +916,7 @@ hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (sample.event.type && callback)
|
if (sample.event.type && callback)
|
||||||
callback (DC_SAMPLE_EVENT, &sample, userdata);
|
callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||||
|
|
||||||
// Manual Gas Set & Change
|
// Manual Gas Set & Change
|
||||||
if (events & 0x10) {
|
if (events & 0x10) {
|
||||||
@ -917,24 +926,22 @@ hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t
|
|||||||
}
|
}
|
||||||
unsigned int o2 = data[offset];
|
unsigned int o2 = data[offset];
|
||||||
unsigned int he = data[offset + 1];
|
unsigned int he = data[offset + 1];
|
||||||
unsigned int idx = hw_ostc_find_gasmix_manual (parser, o2, he, ccr);
|
unsigned int idx = hw_ostc_find_gasmix (parser, o2, he, ccr, MANUAL);
|
||||||
if (idx >= parser->ngasmixes) {
|
if (idx >= parser->ngasmixes) {
|
||||||
if (idx >= NGASMIXES) {
|
if (idx >= NGASMIXES) {
|
||||||
ERROR (abstract->context, "Maximum number of gas mixes reached.");
|
ERROR (abstract->context, "Maximum number of gas mixes reached.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
}
|
}
|
||||||
parser->gasmix[idx].id = 0;
|
|
||||||
parser->gasmix[idx].oxygen = o2;
|
parser->gasmix[idx].oxygen = o2;
|
||||||
parser->gasmix[idx].helium = he;
|
parser->gasmix[idx].helium = he;
|
||||||
parser->gasmix[idx].type = 0;
|
parser->gasmix[idx].type = 0;
|
||||||
parser->gasmix[idx].enabled = 1;
|
parser->gasmix[idx].enabled = 1;
|
||||||
parser->gasmix[idx].active = 1;
|
|
||||||
parser->gasmix[idx].diluent = ccr;
|
parser->gasmix[idx].diluent = ccr;
|
||||||
parser->ngasmixes = idx + 1;
|
parser->ngasmixes = idx + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sample.gasmix = idx;
|
sample.gasmix = idx;
|
||||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
length -= 2;
|
length -= 2;
|
||||||
}
|
}
|
||||||
@ -945,20 +952,19 @@ hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t
|
|||||||
ERROR (abstract->context, "Buffer overflow detected!");
|
ERROR (abstract->context, "Buffer overflow detected!");
|
||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
}
|
}
|
||||||
unsigned int id = data[offset];
|
unsigned int idx = data[offset];
|
||||||
if (parser->model == OSTC4 && ccr && id > parser->nfixed) {
|
if (parser->model == OSTC4 && ccr && idx > parser->nfixed) {
|
||||||
// Fix the OSTC4 diluent index.
|
// Fix the OSTC4 diluent index.
|
||||||
id -= parser->nfixed;
|
idx -= parser->nfixed;
|
||||||
}
|
}
|
||||||
if (id < 1 || id > parser->nfixed) {
|
if (idx < 1 || idx > parser->nfixed) {
|
||||||
ERROR(abstract->context, "Invalid gas mix (%u).", id);
|
ERROR(abstract->context, "Invalid gas mix (%u).", idx);
|
||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
}
|
}
|
||||||
unsigned int idx = hw_ostc_find_gasmix_fixed (parser, id);
|
idx--; /* Convert to a zero based index. */
|
||||||
parser->gasmix[idx].active = 1;
|
|
||||||
sample.gasmix = idx;
|
sample.gasmix = idx;
|
||||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
tank = id - 1;
|
tank = idx;
|
||||||
offset++;
|
offset++;
|
||||||
length--;
|
length--;
|
||||||
}
|
}
|
||||||
@ -971,7 +977,7 @@ hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t
|
|||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
}
|
}
|
||||||
sample.setpoint = data[offset] / 100.0;
|
sample.setpoint = data[offset] / 100.0;
|
||||||
if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
|
||||||
offset++;
|
offset++;
|
||||||
length--;
|
length--;
|
||||||
}
|
}
|
||||||
@ -985,24 +991,22 @@ hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t
|
|||||||
|
|
||||||
unsigned int o2 = data[offset];
|
unsigned int o2 = data[offset];
|
||||||
unsigned int he = data[offset + 1];
|
unsigned int he = data[offset + 1];
|
||||||
unsigned int idx = hw_ostc_find_gasmix_manual (parser, o2, he, 0);
|
unsigned int idx = hw_ostc_find_gasmix (parser, o2, he, 0, MANUAL);
|
||||||
if (idx >= parser->ngasmixes) {
|
if (idx >= parser->ngasmixes) {
|
||||||
if (idx >= NGASMIXES) {
|
if (idx >= NGASMIXES) {
|
||||||
ERROR (abstract->context, "Maximum number of gas mixes reached.");
|
ERROR (abstract->context, "Maximum number of gas mixes reached.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
}
|
}
|
||||||
parser->gasmix[idx].id = 0;
|
|
||||||
parser->gasmix[idx].oxygen = o2;
|
parser->gasmix[idx].oxygen = o2;
|
||||||
parser->gasmix[idx].helium = he;
|
parser->gasmix[idx].helium = he;
|
||||||
parser->gasmix[idx].type = 0;
|
parser->gasmix[idx].type = 0;
|
||||||
parser->gasmix[idx].enabled = 1;
|
parser->gasmix[idx].enabled = 1;
|
||||||
parser->gasmix[idx].active = 1;
|
|
||||||
parser->gasmix[idx].diluent = 0;
|
parser->gasmix[idx].diluent = 0;
|
||||||
parser->ngasmixes = idx + 1;
|
parser->ngasmixes = idx + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sample.gasmix = idx;
|
sample.gasmix = idx;
|
||||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
length -= 2;
|
length -= 2;
|
||||||
}
|
}
|
||||||
@ -1034,7 +1038,7 @@ hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t
|
|||||||
case TEMPERATURE:
|
case TEMPERATURE:
|
||||||
value = array_uint16_le (data + offset);
|
value = array_uint16_le (data + offset);
|
||||||
sample.temperature = value / 10.0;
|
sample.temperature = value / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
break;
|
break;
|
||||||
case DECO:
|
case DECO:
|
||||||
// Due to a firmware bug, the deco/ndl info is incorrect for
|
// Due to a firmware bug, the deco/ndl info is incorrect for
|
||||||
@ -1049,8 +1053,7 @@ hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t
|
|||||||
sample.deco.depth = 0.0;
|
sample.deco.depth = 0.0;
|
||||||
}
|
}
|
||||||
sample.deco.time = data[offset + 1] * 60;
|
sample.deco.time = data[offset + 1] * 60;
|
||||||
sample.deco.tts = 0;
|
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
|
||||||
break;
|
break;
|
||||||
case PPO2:
|
case PPO2:
|
||||||
for (unsigned int j = 0; j < 3; ++j) {
|
for (unsigned int j = 0; j < 3; ++j) {
|
||||||
@ -1064,9 +1067,8 @@ hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t
|
|||||||
}
|
}
|
||||||
if (count) {
|
if (count) {
|
||||||
for (unsigned int j = 0; j < 3; ++j) {
|
for (unsigned int j = 0; j < 3; ++j) {
|
||||||
sample.ppo2.sensor = i;
|
sample.ppo2 = ppo2[j] / 100.0;
|
||||||
sample.ppo2.value = ppo2[j] / 100.0;
|
if (callback) callback (DC_SAMPLE_PPO2, sample, userdata);
|
||||||
if (callback) callback (DC_SAMPLE_PPO2, &sample, userdata);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1075,7 +1077,7 @@ hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t
|
|||||||
sample.cns = array_uint16_le (data + offset) / 100.0;
|
sample.cns = array_uint16_le (data + offset) / 100.0;
|
||||||
else
|
else
|
||||||
sample.cns = data[offset] / 100.0;
|
sample.cns = data[offset] / 100.0;
|
||||||
if (callback) callback (DC_SAMPLE_CNS, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
|
||||||
break;
|
break;
|
||||||
case TANK:
|
case TANK:
|
||||||
value = array_uint16_le (data + offset);
|
value = array_uint16_le (data + offset);
|
||||||
@ -1088,7 +1090,7 @@ hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t
|
|||||||
(firmware >= OSTC3FW(10,40) && firmware <= OSTC3FW(10,50))) {
|
(firmware >= OSTC3FW(10,40) && firmware <= OSTC3FW(10,50))) {
|
||||||
sample.pressure.value /= 10.0;
|
sample.pressure.value /= 10.0;
|
||||||
}
|
}
|
||||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: // Not yet used.
|
default: // Not yet used.
|
||||||
@ -1108,7 +1110,7 @@ hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t
|
|||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
}
|
}
|
||||||
sample.setpoint = data[offset] / 100.0;
|
sample.setpoint = data[offset] / 100.0;
|
||||||
if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
|
||||||
offset++;
|
offset++;
|
||||||
length--;
|
length--;
|
||||||
}
|
}
|
||||||
@ -1122,24 +1124,22 @@ hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t
|
|||||||
|
|
||||||
unsigned int o2 = data[offset];
|
unsigned int o2 = data[offset];
|
||||||
unsigned int he = data[offset + 1];
|
unsigned int he = data[offset + 1];
|
||||||
unsigned int idx = hw_ostc_find_gasmix_manual (parser, o2, he, 0);
|
unsigned int idx = hw_ostc_find_gasmix (parser, o2, he, 0, MANUAL);
|
||||||
if (idx >= parser->ngasmixes) {
|
if (idx >= parser->ngasmixes) {
|
||||||
if (idx >= NGASMIXES) {
|
if (idx >= NGASMIXES) {
|
||||||
ERROR (abstract->context, "Maximum number of gas mixes reached.");
|
ERROR (abstract->context, "Maximum number of gas mixes reached.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
}
|
}
|
||||||
parser->gasmix[idx].id = 0;
|
|
||||||
parser->gasmix[idx].oxygen = o2;
|
parser->gasmix[idx].oxygen = o2;
|
||||||
parser->gasmix[idx].helium = he;
|
parser->gasmix[idx].helium = he;
|
||||||
parser->gasmix[idx].type = 0;
|
parser->gasmix[idx].type = 0;
|
||||||
parser->gasmix[idx].enabled = 1;
|
parser->gasmix[idx].enabled = 1;
|
||||||
parser->gasmix[idx].active = 1;
|
|
||||||
parser->gasmix[idx].diluent = 0;
|
parser->gasmix[idx].diluent = 0;
|
||||||
parser->ngasmixes = idx + 1;
|
parser->ngasmixes = idx + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sample.gasmix = idx;
|
sample.gasmix = idx;
|
||||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
length -= 2;
|
length -= 2;
|
||||||
}
|
}
|
||||||
@ -1157,50 +1157,7 @@ hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t
|
|||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the disabled gas mixes from the fixed gas mixes.
|
|
||||||
unsigned int ndisabled = 0, nenabled = 0;
|
|
||||||
unsigned int count = parser->nfixed - parser->ndisabled;
|
|
||||||
for (unsigned int i = 0; i < count; ++i) {
|
|
||||||
if (parser->gasmix[i].enabled || parser->gasmix[i].active) {
|
|
||||||
// Move the fixed gas mix.
|
|
||||||
parser->gasmix[nenabled] = parser->gasmix[i];
|
|
||||||
nenabled++;
|
|
||||||
} else {
|
|
||||||
ndisabled++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move all the manual gas mixes.
|
|
||||||
memmove (parser->gasmix + nenabled, parser->gasmix + count,
|
|
||||||
(parser->ngasmixes - count) * sizeof (hw_ostc_gasmix_t));
|
|
||||||
memset (parser->gasmix + parser->ngasmixes - ndisabled, 0,
|
|
||||||
ndisabled * sizeof (hw_ostc_gasmix_t));
|
|
||||||
|
|
||||||
// Adjust the counts.
|
|
||||||
parser->ngasmixes -= ndisabled;
|
|
||||||
parser->ndisabled += ndisabled;
|
|
||||||
|
|
||||||
parser->cached = PROFILE;
|
parser->cached = PROFILE;
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
|
|
||||||
{
|
|
||||||
hw_ostc_parser_t *parser = (hw_ostc_parser_t *) abstract;
|
|
||||||
|
|
||||||
// Cache the header data.
|
|
||||||
dc_status_t rc = hw_ostc_parser_cache (parser);
|
|
||||||
if (rc != DC_STATUS_SUCCESS)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
// Cache the profile data.
|
|
||||||
if (parser->cached < PROFILE) {
|
|
||||||
rc = hw_ostc_parser_internal_foreach (parser, NULL, NULL);
|
|
||||||
if (rc != DC_STATUS_SUCCESS)
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hw_ostc_parser_internal_foreach (parser, callback, userdata);
|
|
||||||
}
|
|
||||||
|
|||||||
@ -47,6 +47,7 @@
|
|||||||
#include "context-private.h"
|
#include "context-private.h"
|
||||||
#include "iostream-private.h"
|
#include "iostream-private.h"
|
||||||
#include "iterator-private.h"
|
#include "iterator-private.h"
|
||||||
|
#include "descriptor-private.h"
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
@ -225,7 +226,7 @@ dc_irda_iterator_new (dc_iterator_t **out, dc_context_t *context, dc_descriptor_
|
|||||||
INFO (context, "Discover: address=%08x, name=%s, charset=%02x, hints=%04x",
|
INFO (context, "Discover: address=%08x, name=%s, charset=%02x, hints=%04x",
|
||||||
address, name, charset, hints);
|
address, name, charset, hints);
|
||||||
|
|
||||||
if (!dc_descriptor_filter (descriptor, DC_TRANSPORT_IRDA, name)) {
|
if (!dc_descriptor_filter (descriptor, DC_TRANSPORT_IRDA, name, NULL)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -34,7 +34,6 @@ dc_descriptor_get_product
|
|||||||
dc_descriptor_get_type
|
dc_descriptor_get_type
|
||||||
dc_descriptor_get_model
|
dc_descriptor_get_model
|
||||||
dc_descriptor_get_transports
|
dc_descriptor_get_transports
|
||||||
dc_descriptor_filter
|
|
||||||
|
|
||||||
dc_iostream_get_transport
|
dc_iostream_get_transport
|
||||||
dc_iostream_set_timeout
|
dc_iostream_set_timeout
|
||||||
@ -92,11 +91,17 @@ dc_parser_set_clock
|
|||||||
dc_parser_set_atmospheric
|
dc_parser_set_atmospheric
|
||||||
dc_parser_set_density
|
dc_parser_set_density
|
||||||
dc_parser_get_type
|
dc_parser_get_type
|
||||||
|
dc_parser_set_data
|
||||||
dc_parser_get_datetime
|
dc_parser_get_datetime
|
||||||
dc_parser_get_field
|
dc_parser_get_field
|
||||||
dc_parser_samples_foreach
|
dc_parser_samples_foreach
|
||||||
dc_parser_destroy
|
dc_parser_destroy
|
||||||
|
|
||||||
|
reefnet_sensus_parser_set_calibration
|
||||||
|
reefnet_sensuspro_parser_set_calibration
|
||||||
|
reefnet_sensusultra_parser_set_calibration
|
||||||
|
atomics_cobalt_parser_set_calibration
|
||||||
|
|
||||||
dc_device_open
|
dc_device_open
|
||||||
dc_device_close
|
dc_device_close
|
||||||
dc_device_dump
|
dc_device_dump
|
||||||
|
|||||||
@ -67,12 +67,12 @@
|
|||||||
#define RB_LOGBOOK_BEGIN (1 * PAGESIZE)
|
#define RB_LOGBOOK_BEGIN (1 * PAGESIZE)
|
||||||
#define RB_LOGBOOK_END (25 * PAGESIZE)
|
#define RB_LOGBOOK_END (25 * PAGESIZE)
|
||||||
#define RB_LOGBOOK_SIZE (RB_LOGBOOK_END - RB_LOGBOOK_BEGIN)
|
#define RB_LOGBOOK_SIZE (RB_LOGBOOK_END - RB_LOGBOOK_BEGIN)
|
||||||
#define RB_LOGBOOK_DISTANCE(a,b) ringbuffer_distance (a, b, DC_RINGBUFFER_FULL, RB_LOGBOOK_BEGIN, RB_LOGBOOK_END)
|
#define RB_LOGBOOK_DISTANCE(a,b) ringbuffer_distance (a, b, 1, RB_LOGBOOK_BEGIN, RB_LOGBOOK_END)
|
||||||
|
|
||||||
#define RB_PROFILE_BEGIN (25 * PAGESIZE)
|
#define RB_PROFILE_BEGIN (25 * PAGESIZE)
|
||||||
#define RB_PROFILE_END (500 * PAGESIZE)
|
#define RB_PROFILE_END (500 * PAGESIZE)
|
||||||
#define RB_PROFILE_SIZE (RB_PROFILE_END - RB_PROFILE_BEGIN)
|
#define RB_PROFILE_SIZE (RB_PROFILE_END - RB_PROFILE_BEGIN)
|
||||||
#define RB_PROFILE_DISTANCE(a,b) ringbuffer_distance (a, b, DC_RINGBUFFER_FULL, RB_PROFILE_BEGIN, RB_PROFILE_END)
|
#define RB_PROFILE_DISTANCE(a,b) ringbuffer_distance (a, b, 1, RB_PROFILE_BEGIN, RB_PROFILE_END)
|
||||||
|
|
||||||
#define SZ_HEADER_XEN 80
|
#define SZ_HEADER_XEN 80
|
||||||
#define SZ_HEADER_OTHER 96
|
#define SZ_HEADER_OTHER 96
|
||||||
@ -469,7 +469,7 @@ liquivision_lynx_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
|
|||||||
|
|
||||||
// Create the ringbuffer stream.
|
// Create the ringbuffer stream.
|
||||||
dc_rbstream_t *rblogbook = NULL;
|
dc_rbstream_t *rblogbook = NULL;
|
||||||
status = dc_rbstream_new (&rblogbook, abstract, SEGMENTSIZE, SEGMENTSIZE, RB_LOGBOOK_BEGIN, RB_LOGBOOK_END, rb_logbook_end, DC_RBSTREAM_BACKWARD);
|
status = dc_rbstream_new (&rblogbook, abstract, SEGMENTSIZE, SEGMENTSIZE, RB_LOGBOOK_BEGIN, RB_LOGBOOK_END, rb_logbook_end);
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
ERROR (abstract->context, "Failed to create the ringbuffer stream.");
|
ERROR (abstract->context, "Failed to create the ringbuffer stream.");
|
||||||
goto error_free_logbook;
|
goto error_free_logbook;
|
||||||
@ -600,7 +600,7 @@ liquivision_lynx_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
|
|||||||
|
|
||||||
// Create the ringbuffer stream.
|
// Create the ringbuffer stream.
|
||||||
dc_rbstream_t *rbprofile = NULL;
|
dc_rbstream_t *rbprofile = NULL;
|
||||||
status = dc_rbstream_new (&rbprofile, abstract, SEGMENTSIZE, SEGMENTSIZE, RB_PROFILE_BEGIN, RB_PROFILE_END, rb_profile_end, DC_RBSTREAM_BACKWARD);
|
status = dc_rbstream_new (&rbprofile, abstract, SEGMENTSIZE, SEGMENTSIZE, RB_PROFILE_BEGIN, RB_PROFILE_END, rb_profile_end);
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
ERROR (abstract->context, "Failed to create the ringbuffer stream.");
|
ERROR (abstract->context, "Failed to create the ringbuffer stream.");
|
||||||
goto error_free_profile;
|
goto error_free_profile;
|
||||||
|
|||||||
@ -35,7 +35,7 @@ dc_status_t
|
|||||||
liquivision_lynx_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
liquivision_lynx_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
liquivision_lynx_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
liquivision_lynx_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -117,6 +117,7 @@ struct liquivision_lynx_parser_t {
|
|||||||
liquivision_lynx_tank_t tank[NTANKS];
|
liquivision_lynx_tank_t tank[NTANKS];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static dc_status_t liquivision_lynx_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t liquivision_lynx_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t liquivision_lynx_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t liquivision_lynx_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t liquivision_lynx_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t liquivision_lynx_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t liquivision_lynx_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -124,6 +125,7 @@ static dc_status_t liquivision_lynx_parser_samples_foreach (dc_parser_t *abstrac
|
|||||||
static const dc_parser_vtable_t liquivision_lynx_parser_vtable = {
|
static const dc_parser_vtable_t liquivision_lynx_parser_vtable = {
|
||||||
sizeof(liquivision_lynx_parser_t),
|
sizeof(liquivision_lynx_parser_t),
|
||||||
DC_FAMILY_LIQUIVISION_LYNX,
|
DC_FAMILY_LIQUIVISION_LYNX,
|
||||||
|
liquivision_lynx_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -135,7 +137,7 @@ static const dc_parser_vtable_t liquivision_lynx_parser_vtable = {
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
liquivision_lynx_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
liquivision_lynx_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||||
{
|
{
|
||||||
liquivision_lynx_parser_t *parser = NULL;
|
liquivision_lynx_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -143,7 +145,7 @@ liquivision_lynx_parser_create (dc_parser_t **out, dc_context_t *context, const
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (liquivision_lynx_parser_t *) dc_parser_allocate (context, &liquivision_lynx_parser_vtable, data, size);
|
parser = (liquivision_lynx_parser_t *) dc_parser_allocate (context, &liquivision_lynx_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -171,6 +173,29 @@ liquivision_lynx_parser_create (dc_parser_t **out, dc_context_t *context, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
liquivision_lynx_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
liquivision_lynx_parser_t *parser = (liquivision_lynx_parser_t *) abstract;
|
||||||
|
|
||||||
|
// Reset the cache.
|
||||||
|
parser->cached = 0;
|
||||||
|
parser->ngasmixes = 0;
|
||||||
|
parser->ntanks = 0;
|
||||||
|
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||||
|
parser->gasmix[i].oxygen = 0;
|
||||||
|
parser->gasmix[i].helium = 0;
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i < NTANKS; ++i) {
|
||||||
|
parser->tank[i].id = 0;
|
||||||
|
parser->tank[i].beginpressure = 0;
|
||||||
|
parser->tank[i].endpressure = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
liquivision_lynx_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
liquivision_lynx_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -290,7 +315,6 @@ liquivision_lynx_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
|
|||||||
*((unsigned int *) value) = parser->ngasmixes;
|
*((unsigned int *) value) = parser->ngasmixes;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
||||||
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
||||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||||
@ -305,7 +329,6 @@ liquivision_lynx_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
|
|||||||
tank->beginpressure = parser->tank[flags].beginpressure / 100.0;
|
tank->beginpressure = parser->tank[flags].beginpressure / 100.0;
|
||||||
tank->endpressure = parser->tank[flags].endpressure / 100.0;
|
tank->endpressure = parser->tank[flags].endpressure / 100.0;
|
||||||
tank->gasmix = DC_GASMIX_UNKNOWN;
|
tank->gasmix = DC_GASMIX_UNKNOWN;
|
||||||
tank->usage = DC_USAGE_NONE;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return DC_STATUS_UNSUPPORTED;
|
return DC_STATUS_UNSUPPORTED;
|
||||||
@ -522,29 +545,29 @@ liquivision_lynx_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
|
|
||||||
// Time (seconds).
|
// Time (seconds).
|
||||||
time += interval;
|
time += interval;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Depth (1/100 m).
|
// Depth (1/100 m).
|
||||||
sample.depth = value / 100.0;
|
sample.depth = value / 100.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
// Temperature (1/10 °C).
|
// Temperature (1/10 °C).
|
||||||
int temperature = (signed short) array_uint16_le (data + offset);
|
int temperature = (signed short) array_uint16_le (data + offset);
|
||||||
sample.temperature = temperature / 10.0;
|
sample.temperature = temperature / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
|
|
||||||
// Gas mix
|
// Gas mix
|
||||||
if (have_gasmix) {
|
if (have_gasmix) {
|
||||||
sample.gasmix = gasmix_idx;
|
sample.gasmix = gasmix_idx;
|
||||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
have_gasmix = 0;
|
have_gasmix = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setpoint (1/10 bar).
|
// Setpoint (1/10 bar).
|
||||||
if (have_setpoint) {
|
if (have_setpoint) {
|
||||||
sample.setpoint = setpoint / 10.0;
|
sample.setpoint = setpoint / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
|
||||||
have_setpoint = 0;
|
have_setpoint = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,7 +577,7 @@ liquivision_lynx_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
if (have_pressure & (1 << i)) {
|
if (have_pressure & (1 << i)) {
|
||||||
sample.pressure.tank = i;
|
sample.pressure.tank = i;
|
||||||
sample.pressure.value = pressure[i] / 100.0;
|
sample.pressure.value = pressure[i] / 100.0;
|
||||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
have_pressure = 0;
|
have_pressure = 0;
|
||||||
@ -570,8 +593,7 @@ liquivision_lynx_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
|||||||
sample.deco.depth = 0.0;
|
sample.deco.depth = 0.0;
|
||||||
}
|
}
|
||||||
sample.deco.time = 0;
|
sample.deco.time = 0;
|
||||||
sample.deco.tts = 0;
|
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
|
||||||
have_deco = 0;
|
have_deco = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,7 @@ dc_status_t
|
|||||||
mares_darwin_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
mares_darwin_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
mares_darwin_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
mares_darwin_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,6 +47,7 @@ struct mares_darwin_parser_t {
|
|||||||
unsigned int samplesize;
|
unsigned int samplesize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static dc_status_t mares_darwin_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t mares_darwin_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t mares_darwin_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t mares_darwin_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t mares_darwin_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -54,6 +55,7 @@ static dc_status_t mares_darwin_parser_samples_foreach (dc_parser_t *abstract, d
|
|||||||
static const dc_parser_vtable_t mares_darwin_parser_vtable = {
|
static const dc_parser_vtable_t mares_darwin_parser_vtable = {
|
||||||
sizeof(mares_darwin_parser_t),
|
sizeof(mares_darwin_parser_t),
|
||||||
DC_FAMILY_MARES_DARWIN,
|
DC_FAMILY_MARES_DARWIN,
|
||||||
|
mares_darwin_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -65,7 +67,7 @@ static const dc_parser_vtable_t mares_darwin_parser_vtable = {
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
mares_darwin_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
mares_darwin_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||||
{
|
{
|
||||||
mares_darwin_parser_t *parser = NULL;
|
mares_darwin_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -73,7 +75,7 @@ mares_darwin_parser_create (dc_parser_t **out, dc_context_t *context, const unsi
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (mares_darwin_parser_t *) dc_parser_allocate (context, &mares_darwin_parser_vtable, data, size);
|
parser = (mares_darwin_parser_t *) dc_parser_allocate (context, &mares_darwin_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -95,6 +97,13 @@ mares_darwin_parser_create (dc_parser_t **out, dc_context_t *context, const unsi
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
mares_darwin_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
mares_darwin_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
mares_darwin_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -150,7 +159,6 @@ mares_darwin_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
gasmix->helium = 0.0;
|
gasmix->helium = 0.0;
|
||||||
if (mode == NITROX) {
|
if (mode == NITROX) {
|
||||||
gasmix->oxygen = p[0x0E] / 100.0;
|
gasmix->oxygen = p[0x0E] / 100.0;
|
||||||
@ -177,7 +185,6 @@ mares_darwin_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
|
|||||||
tank->gasmix = 0;
|
tank->gasmix = 0;
|
||||||
tank->beginpressure = array_uint16_be (p + 0x17);
|
tank->beginpressure = array_uint16_be (p + 0x17);
|
||||||
tank->endpressure = array_uint16_be (p + 0x19);
|
tank->endpressure = array_uint16_be (p + 0x19);
|
||||||
tank->usage = DC_USAGE_NONE;
|
|
||||||
} else {
|
} else {
|
||||||
return DC_STATUS_UNSUPPORTED;
|
return DC_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
@ -235,17 +242,17 @@ mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
|||||||
|
|
||||||
// Surface Time (seconds).
|
// Surface Time (seconds).
|
||||||
time += 20;
|
time += 20;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Depth (1/10 m).
|
// Depth (1/10 m).
|
||||||
sample.depth = depth / 10.0;
|
sample.depth = depth / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
// Gas change.
|
// Gas change.
|
||||||
if (gasmix != gasmix_previous) {
|
if (gasmix != gasmix_previous) {
|
||||||
sample.gasmix = gasmix;
|
sample.gasmix = gasmix;
|
||||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
gasmix_previous = gasmix;
|
gasmix_previous = gasmix;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,7 +262,7 @@ mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
|||||||
sample.event.time = 0;
|
sample.event.time = 0;
|
||||||
sample.event.flags = 0;
|
sample.event.flags = 0;
|
||||||
sample.event.value = ascent;
|
sample.event.value = ascent;
|
||||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deco violation
|
// Deco violation
|
||||||
@ -264,7 +271,7 @@ mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
|||||||
sample.event.time = 0;
|
sample.event.time = 0;
|
||||||
sample.event.flags = 0;
|
sample.event.flags = 0;
|
||||||
sample.event.value = 0;
|
sample.event.value = 0;
|
||||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deco stop
|
// Deco stop
|
||||||
@ -275,8 +282,7 @@ mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
|||||||
}
|
}
|
||||||
sample.deco.time = 0;
|
sample.deco.time = 0;
|
||||||
sample.deco.depth = 0.0;
|
sample.deco.depth = 0.0;
|
||||||
sample.deco.tts = 0;
|
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
|
||||||
|
|
||||||
if (parser->samplesize == 3) {
|
if (parser->samplesize == 3) {
|
||||||
unsigned int type = (time / 20 + 2) % 3;
|
unsigned int type = (time / 20 + 2) % 3;
|
||||||
@ -285,7 +291,7 @@ mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
|||||||
pressure -= abstract->data[offset + 2];
|
pressure -= abstract->data[offset + 2];
|
||||||
sample.pressure.tank = 0;
|
sample.pressure.tank = 0;
|
||||||
sample.pressure.value = pressure;
|
sample.pressure.value = pressure;
|
||||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <string.h> // memcpy, memcmp
|
#include <string.h> // memcpy, memcmp
|
||||||
#include <stdlib.h> // malloc, free
|
#include <stdlib.h> // malloc, free
|
||||||
|
#include <assert.h> // assert
|
||||||
|
|
||||||
#include "mares_iconhd.h"
|
#include "mares_iconhd.h"
|
||||||
#include "context-private.h"
|
#include "context-private.h"
|
||||||
@ -48,39 +49,11 @@
|
|||||||
#define SMARTAIR 0x24
|
#define SMARTAIR 0x24
|
||||||
#define QUAD 0x29
|
#define QUAD 0x29
|
||||||
#define HORIZON 0x2C
|
#define HORIZON 0x2C
|
||||||
#define PUCKAIR2 0x2D
|
|
||||||
#define SIRIUS 0x2F
|
|
||||||
#define QUADCI 0x31
|
|
||||||
#define PUCK4 0x35
|
|
||||||
|
|
||||||
#define ISSMART(model) ( \
|
|
||||||
(model) == SMART || \
|
|
||||||
(model) == SMARTAPNEA || \
|
|
||||||
(model) == SMARTAIR)
|
|
||||||
|
|
||||||
#define ISGENIUS(model) ( \
|
|
||||||
(model) == GENIUS || \
|
|
||||||
(model) == HORIZON || \
|
|
||||||
(model) == PUCKAIR2 || \
|
|
||||||
(model) == SIRIUS || \
|
|
||||||
(model) == QUADCI || \
|
|
||||||
(model) == PUCK4)
|
|
||||||
|
|
||||||
#define ISSIRIUS(model) ( \
|
|
||||||
(model) == PUCKAIR2 || \
|
|
||||||
(model) == SIRIUS || \
|
|
||||||
(model) == QUADCI || \
|
|
||||||
(model) == PUCK4)
|
|
||||||
|
|
||||||
#define MAXRETRIES 4
|
#define MAXRETRIES 4
|
||||||
|
|
||||||
#define MAXPACKET 244
|
|
||||||
|
|
||||||
#define FIXED 0
|
|
||||||
#define VARIABLE 1
|
|
||||||
|
|
||||||
#define ACK 0xAA
|
#define ACK 0xAA
|
||||||
#define END 0xEA
|
#define EOF 0xEA
|
||||||
#define XOR 0xA5
|
#define XOR 0xA5
|
||||||
|
|
||||||
#define CMD_VERSION 0xC2
|
#define CMD_VERSION 0xC2
|
||||||
@ -90,8 +63,6 @@
|
|||||||
#define CMD_OBJ_EVEN 0xAC
|
#define CMD_OBJ_EVEN 0xAC
|
||||||
#define CMD_OBJ_ODD 0xFE
|
#define CMD_OBJ_ODD 0xFE
|
||||||
|
|
||||||
#define OBJ_DEVICE 0x2000
|
|
||||||
#define OBJ_DEVICE_SERIAL 0x04
|
|
||||||
#define OBJ_LOGBOOK 0x2008
|
#define OBJ_LOGBOOK 0x2008
|
||||||
#define OBJ_LOGBOOK_COUNT 0x01
|
#define OBJ_LOGBOOK_COUNT 0x01
|
||||||
#define OBJ_DIVE 0x3000
|
#define OBJ_DIVE 0x3000
|
||||||
@ -123,7 +94,6 @@ typedef struct mares_iconhd_device_t {
|
|||||||
unsigned char version[140];
|
unsigned char version[140];
|
||||||
unsigned int model;
|
unsigned int model;
|
||||||
unsigned int packetsize;
|
unsigned int packetsize;
|
||||||
unsigned int ble;
|
|
||||||
} mares_iconhd_device_t;
|
} mares_iconhd_device_t;
|
||||||
|
|
||||||
static dc_status_t mares_iconhd_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
|
static dc_status_t mares_iconhd_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
|
||||||
@ -191,10 +161,6 @@ mares_iconhd_get_model (mares_iconhd_device_t *device)
|
|||||||
{"Smart Air", SMARTAIR},
|
{"Smart Air", SMARTAIR},
|
||||||
{"Quad", QUAD},
|
{"Quad", QUAD},
|
||||||
{"Horizon", HORIZON},
|
{"Horizon", HORIZON},
|
||||||
{"Puck Air 2", PUCKAIR2},
|
|
||||||
{"Sirius", SIRIUS},
|
|
||||||
{"Quad Ci", QUADCI},
|
|
||||||
{"Puck4", PUCK4},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check the product name in the version packet against the list
|
// Check the product name in the version packet against the list
|
||||||
@ -211,57 +177,44 @@ mares_iconhd_get_model (mares_iconhd_device_t *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
mares_iconhd_packet_fixed (mares_iconhd_device_t *device,
|
mares_iconhd_packet (mares_iconhd_device_t *device,
|
||||||
unsigned char cmd,
|
const unsigned char command[], unsigned int csize,
|
||||||
const unsigned char data[], unsigned int size,
|
unsigned char answer[], unsigned int asize)
|
||||||
unsigned char answer[], unsigned int asize,
|
|
||||||
unsigned int *actual)
|
|
||||||
{
|
{
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
dc_status_t status = DC_STATUS_SUCCESS;
|
||||||
dc_device_t *abstract = (dc_device_t *) device;
|
dc_device_t *abstract = (dc_device_t *) device;
|
||||||
dc_transport_t transport = dc_iostream_get_transport (device->iostream);
|
|
||||||
|
assert (csize >= 2);
|
||||||
|
|
||||||
if (device_is_cancelled (abstract))
|
if (device_is_cancelled (abstract))
|
||||||
return DC_STATUS_CANCELLED;
|
return DC_STATUS_CANCELLED;
|
||||||
|
|
||||||
// Send the command header to the dive computer.
|
// Send the command header to the dive computer.
|
||||||
const unsigned char command[2] = {
|
status = dc_iostream_write (device->iostream, command, 2, NULL);
|
||||||
cmd, cmd ^ XOR,
|
|
||||||
};
|
|
||||||
status = dc_iostream_write (device->iostream, command, sizeof(command), NULL);
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
ERROR (abstract->context, "Failed to send the command header.");
|
ERROR (abstract->context, "Failed to send the command.");
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the command payload to the dive computer.
|
|
||||||
if (size && transport == DC_TRANSPORT_BLE) {
|
|
||||||
status = dc_iostream_write (device->iostream, data, size, NULL);
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to send the command data.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Receive the header byte.
|
// Receive the header byte.
|
||||||
unsigned char header[1] = {0};
|
unsigned char header[1] = {0};
|
||||||
status = dc_iostream_read (device->iostream, header, sizeof (header), NULL);
|
status = dc_iostream_read (device->iostream, header, sizeof (header), NULL);
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
ERROR (abstract->context, "Failed to receive the packet header.");
|
ERROR (abstract->context, "Failed to receive the answer.");
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the header byte.
|
// Verify the header byte.
|
||||||
if (header[0] != ACK) {
|
if (header[0] != ACK) {
|
||||||
ERROR (abstract->context, "Unexpected packet header byte (%02x).", header[0]);
|
ERROR (abstract->context, "Unexpected answer byte.");
|
||||||
return DC_STATUS_PROTOCOL;
|
return DC_STATUS_PROTOCOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the command payload to the dive computer.
|
// Send the command payload to the dive computer.
|
||||||
if (size && transport != DC_TRANSPORT_BLE) {
|
if (csize > 2) {
|
||||||
status = dc_iostream_write (device->iostream, data, size, NULL);
|
status = dc_iostream_write (device->iostream, command + 2, csize - 2, NULL);
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
ERROR (abstract->context, "Failed to send the command data.");
|
ERROR (abstract->context, "Failed to send the command.");
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -269,7 +222,7 @@ mares_iconhd_packet_fixed (mares_iconhd_device_t *device,
|
|||||||
// Read the packet.
|
// Read the packet.
|
||||||
status = dc_iostream_read (device->iostream, answer, asize, NULL);
|
status = dc_iostream_read (device->iostream, answer, asize, NULL);
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
ERROR (abstract->context, "Failed to receive the packet data.");
|
ERROR (abstract->context, "Failed to receive the answer.");
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,130 +230,25 @@ mares_iconhd_packet_fixed (mares_iconhd_device_t *device,
|
|||||||
unsigned char trailer[1] = {0};
|
unsigned char trailer[1] = {0};
|
||||||
status = dc_iostream_read (device->iostream, trailer, sizeof (trailer), NULL);
|
status = dc_iostream_read (device->iostream, trailer, sizeof (trailer), NULL);
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
ERROR (abstract->context, "Failed to receive the packet trailer.");
|
ERROR (abstract->context, "Failed to receive the answer.");
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the trailer byte.
|
// Verify the trailer byte.
|
||||||
if (trailer[0] != END) {
|
if (trailer[0] != EOF) {
|
||||||
ERROR (abstract->context, "Unexpected packet trailer byte (%02x).", trailer[0]);
|
ERROR (abstract->context, "Unexpected answer byte.");
|
||||||
return DC_STATUS_PROTOCOL;
|
return DC_STATUS_PROTOCOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actual) {
|
|
||||||
*actual = asize;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
mares_iconhd_packet_variable (mares_iconhd_device_t *device,
|
mares_iconhd_transfer (mares_iconhd_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize)
|
||||||
unsigned char cmd,
|
|
||||||
const unsigned char data[], unsigned int size,
|
|
||||||
unsigned char answer[], unsigned int asize,
|
|
||||||
unsigned int *actual)
|
|
||||||
{
|
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
|
||||||
dc_device_t *abstract = (dc_device_t *) device;
|
|
||||||
unsigned char packet[MAXPACKET] = {0};
|
|
||||||
size_t length = 0;
|
|
||||||
|
|
||||||
if (device_is_cancelled (abstract))
|
|
||||||
return DC_STATUS_CANCELLED;
|
|
||||||
|
|
||||||
// Send the command header to the dive computer.
|
|
||||||
const unsigned char command[2] = {
|
|
||||||
cmd, cmd ^ XOR,
|
|
||||||
};
|
|
||||||
status = dc_iostream_write (device->iostream, command, sizeof(command), NULL);
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to send the command header.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read either the entire data packet (if there is no command data to send),
|
|
||||||
// or only the header byte (if there is also command data to send).
|
|
||||||
status = dc_iostream_read (device->iostream, packet, sizeof (packet), &length);
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to receive the packet header.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size) {
|
|
||||||
// Send the command payload to the dive computer.
|
|
||||||
status = dc_iostream_write (device->iostream, data, size, NULL);
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to send the command data.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the data packet.
|
|
||||||
size_t len = 0;
|
|
||||||
status = dc_iostream_read (device->iostream, packet + length, sizeof (packet) - length, &len);
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to receive the packet data.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
length += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length < 2 || length - 2 > asize) {
|
|
||||||
ERROR (abstract->context, "Unexpected packet length (" DC_PRINTF_SIZE ").", length);
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the header byte.
|
|
||||||
if (packet[0] != ACK) {
|
|
||||||
ERROR (abstract->context, "Unexpected packet header byte (%02x).", packet[0]);
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the trailer byte.
|
|
||||||
if (packet[length - 1] != END) {
|
|
||||||
ERROR (abstract->context, "Unexpected packet trailer byte (%02x).", packet[length - 1]);
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actual == NULL) {
|
|
||||||
// Verify the actual length.
|
|
||||||
if (length - 2 != asize) {
|
|
||||||
ERROR (abstract->context, "Unexpected packet length (" DC_PRINTF_SIZE ").", length - 2);
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Return the actual length.
|
|
||||||
*actual = length - 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy (answer, packet + 1, length - 2);
|
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
mares_iconhd_packet (mares_iconhd_device_t *device,
|
|
||||||
unsigned char cmd,
|
|
||||||
const unsigned char data[], unsigned int size,
|
|
||||||
unsigned char answer[], unsigned int asize,
|
|
||||||
unsigned int *actual)
|
|
||||||
{
|
|
||||||
dc_transport_t transport = dc_iostream_get_transport (device->iostream);
|
|
||||||
|
|
||||||
if (transport == DC_TRANSPORT_BLE && device->ble == VARIABLE) {
|
|
||||||
return mares_iconhd_packet_variable (device, cmd, data, size, answer, asize, actual);
|
|
||||||
} else {
|
|
||||||
return mares_iconhd_packet_fixed (device, cmd, data, size, answer, asize, actual);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
mares_iconhd_transfer (mares_iconhd_device_t *device, unsigned char cmd, const unsigned char data[], unsigned int size, unsigned char answer[], unsigned int asize, unsigned int *actual)
|
|
||||||
{
|
{
|
||||||
unsigned int nretries = 0;
|
unsigned int nretries = 0;
|
||||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||||
while ((rc = mares_iconhd_packet (device, cmd, data, size, answer, asize, actual)) != DC_STATUS_SUCCESS) {
|
while ((rc = mares_iconhd_packet (device, command, csize, answer, asize)) != DC_STATUS_SUCCESS) {
|
||||||
// Automatically discard a corrupted packet,
|
// Automatically discard a corrupted packet,
|
||||||
// and request a new one.
|
// and request a new one.
|
||||||
if (rc != DC_STATUS_PROTOCOL && rc != DC_STATUS_TIMEOUT)
|
if (rc != DC_STATUS_PROTOCOL && rc != DC_STATUS_TIMEOUT)
|
||||||
@ -424,9 +272,7 @@ mares_iconhd_read_object(mares_iconhd_device_t *device, dc_event_progress_t *pro
|
|||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
dc_status_t status = DC_STATUS_SUCCESS;
|
||||||
dc_device_t *abstract = (dc_device_t *) device;
|
dc_device_t *abstract = (dc_device_t *) device;
|
||||||
dc_transport_t transport = dc_iostream_get_transport (device->iostream);
|
dc_transport_t transport = dc_iostream_get_transport (device->iostream);
|
||||||
const unsigned int maxpacket = (transport == DC_TRANSPORT_BLE) ?
|
const unsigned int maxpacket = (transport == DC_TRANSPORT_BLE) ? 124 : 504;
|
||||||
(device->ble == VARIABLE ? MAXPACKET - 3 : 124) :
|
|
||||||
504;
|
|
||||||
|
|
||||||
// Update and emit a progress event.
|
// Update and emit a progress event.
|
||||||
unsigned int initial = 0;
|
unsigned int initial = 0;
|
||||||
@ -437,21 +283,23 @@ mares_iconhd_read_object(mares_iconhd_device_t *device, dc_event_progress_t *pro
|
|||||||
|
|
||||||
// Transfer the init packet.
|
// Transfer the init packet.
|
||||||
unsigned char rsp_init[16];
|
unsigned char rsp_init[16];
|
||||||
unsigned char cmd_init[16] = {
|
unsigned char cmd_init[18] = {
|
||||||
|
CMD_OBJ_INIT,
|
||||||
|
CMD_OBJ_INIT ^ XOR,
|
||||||
0x40,
|
0x40,
|
||||||
(index >> 0) & 0xFF,
|
(index >> 0) & 0xFF,
|
||||||
(index >> 8) & 0xFF,
|
(index >> 8) & 0xFF,
|
||||||
subindex & 0xFF
|
subindex & 0xFF
|
||||||
};
|
};
|
||||||
memset (cmd_init + 6, 0x00, sizeof(cmd_init) - 6);
|
memset (cmd_init + 6, 0x00, sizeof(cmd_init) - 6);
|
||||||
status = mares_iconhd_transfer (device, CMD_OBJ_INIT, cmd_init, sizeof (cmd_init), rsp_init, sizeof (rsp_init), NULL);
|
status = mares_iconhd_transfer (device, cmd_init, sizeof (cmd_init), rsp_init, sizeof (rsp_init));
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
ERROR (abstract->context, "Failed to transfer the init packet.");
|
ERROR (abstract->context, "Failed to transfer the init packet.");
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the packet header.
|
// Verify the packet header.
|
||||||
if (memcmp (cmd_init + 1, rsp_init + 1, 3) != 0) {
|
if (memcmp (cmd_init + 3, rsp_init + 1, 3) != 0) {
|
||||||
ERROR (abstract->context, "Unexpected packet header.");
|
ERROR (abstract->context, "Unexpected packet header.");
|
||||||
return DC_STATUS_PROTOCOL;
|
return DC_STATUS_PROTOCOL;
|
||||||
}
|
}
|
||||||
@ -498,21 +346,14 @@ mares_iconhd_read_object(mares_iconhd_device_t *device, dc_event_progress_t *pro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Transfer the segment packet.
|
// Transfer the segment packet.
|
||||||
unsigned int length = 0;
|
|
||||||
unsigned char rsp_segment[1 + 504];
|
unsigned char rsp_segment[1 + 504];
|
||||||
status = mares_iconhd_transfer (device, cmd, NULL, 0, rsp_segment, len + 1, &length);
|
unsigned char cmd_segment[] = {cmd, cmd ^ XOR};
|
||||||
|
status = mares_iconhd_transfer (device, cmd_segment, sizeof (cmd_segment), rsp_segment, len + 1);
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
ERROR (abstract->context, "Failed to transfer the segment packet.");
|
ERROR (abstract->context, "Failed to transfer the segment packet.");
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length < 1) {
|
|
||||||
ERROR (abstract->context, "Unexpected packet length (%u).", length);
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
length--;
|
|
||||||
|
|
||||||
// Verify the packet header.
|
// Verify the packet header.
|
||||||
if ((rsp_segment[0] & 0xF0) >> 4 != toggle) {
|
if ((rsp_segment[0] & 0xF0) >> 4 != toggle) {
|
||||||
ERROR (abstract->context, "Unexpected packet header (%02x).", rsp_segment[0]);
|
ERROR (abstract->context, "Unexpected packet header (%02x).", rsp_segment[0]);
|
||||||
@ -520,12 +361,12 @@ mares_iconhd_read_object(mares_iconhd_device_t *device, dc_event_progress_t *pro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Append the payload to the output buffer.
|
// Append the payload to the output buffer.
|
||||||
if (!dc_buffer_append (buffer, rsp_segment + 1, length)) {
|
if (!dc_buffer_append (buffer, rsp_segment + 1, len)) {
|
||||||
ERROR (abstract->context, "Insufficient buffer space available.");
|
ERROR (abstract->context, "Insufficient buffer space available.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
nbytes += length;
|
nbytes += len;
|
||||||
npackets++;
|
npackets++;
|
||||||
|
|
||||||
// Update and emit the progress events.
|
// Update and emit the progress events.
|
||||||
@ -539,7 +380,7 @@ mares_iconhd_read_object(mares_iconhd_device_t *device, dc_event_progress_t *pro
|
|||||||
}
|
}
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t *iostream, unsigned int model)
|
mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t *iostream)
|
||||||
{
|
{
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
dc_status_t status = DC_STATUS_SUCCESS;
|
||||||
mares_iconhd_device_t *device = NULL;
|
mares_iconhd_device_t *device = NULL;
|
||||||
@ -562,11 +403,10 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
|
|||||||
memset (device->version, 0, sizeof (device->version));
|
memset (device->version, 0, sizeof (device->version));
|
||||||
device->model = 0;
|
device->model = 0;
|
||||||
device->packetsize = 0;
|
device->packetsize = 0;
|
||||||
device->ble = ISSIRIUS(model) ? VARIABLE : FIXED;
|
|
||||||
|
|
||||||
// Create the packet stream.
|
// Create the packet stream.
|
||||||
if (transport == DC_TRANSPORT_BLE && device->ble == FIXED) {
|
if (transport == DC_TRANSPORT_BLE) {
|
||||||
status = dc_packet_open (&device->iostream, context, iostream, 244, 20);
|
status = dc_packet_open (&device->iostream, context, iostream, 20, 20);
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
ERROR (context, "Failed to create the packet stream.");
|
ERROR (context, "Failed to create the packet stream.");
|
||||||
goto error_free;
|
goto error_free;
|
||||||
@ -607,8 +447,9 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
|
|||||||
dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
|
dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
|
||||||
|
|
||||||
// Send the version command.
|
// Send the version command.
|
||||||
status = mares_iconhd_transfer (device, CMD_VERSION, NULL, 0,
|
unsigned char command[] = {CMD_VERSION, CMD_VERSION ^ XOR};
|
||||||
device->version, sizeof (device->version), NULL);
|
status = mares_iconhd_transfer (device, command, sizeof (command),
|
||||||
|
device->version, sizeof (device->version));
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
goto error_free_iostream;
|
goto error_free_iostream;
|
||||||
}
|
}
|
||||||
@ -619,8 +460,9 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
|
|||||||
// Read the size of the flash memory.
|
// Read the size of the flash memory.
|
||||||
unsigned int memsize = 0;
|
unsigned int memsize = 0;
|
||||||
if (device->model == QUAD) {
|
if (device->model == QUAD) {
|
||||||
|
unsigned char cmd_flash[] = {CMD_FLASHSIZE, CMD_FLASHSIZE ^ XOR};
|
||||||
unsigned char rsp_flash[4] = {0};
|
unsigned char rsp_flash[4] = {0};
|
||||||
status = mares_iconhd_transfer (device, CMD_FLASHSIZE, NULL, 0, rsp_flash, sizeof (rsp_flash), NULL);
|
status = mares_iconhd_transfer (device, cmd_flash, sizeof (cmd_flash), rsp_flash, sizeof (rsp_flash));
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
if (status != DC_STATUS_SUCCESS) {
|
||||||
WARNING (context, "Failed to read the flash memory size.");
|
WARNING (context, "Failed to read the flash memory size.");
|
||||||
} else {
|
} else {
|
||||||
@ -679,7 +521,7 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
|
|||||||
|
|
||||||
|
|
||||||
error_free_iostream:
|
error_free_iostream:
|
||||||
if (transport == DC_TRANSPORT_BLE && device->ble == FIXED) {
|
if (transport == DC_TRANSPORT_BLE) {
|
||||||
dc_iostream_close (device->iostream);
|
dc_iostream_close (device->iostream);
|
||||||
}
|
}
|
||||||
error_free:
|
error_free:
|
||||||
@ -692,10 +534,9 @@ static dc_status_t
|
|||||||
mares_iconhd_device_close (dc_device_t *abstract)
|
mares_iconhd_device_close (dc_device_t *abstract)
|
||||||
{
|
{
|
||||||
mares_iconhd_device_t *device = (mares_iconhd_device_t *) abstract;
|
mares_iconhd_device_t *device = (mares_iconhd_device_t *) abstract;
|
||||||
dc_transport_t transport = dc_iostream_get_transport (device->iostream);
|
|
||||||
|
|
||||||
// Close the packet stream.
|
// Close the packet stream.
|
||||||
if (transport == DC_TRANSPORT_BLE && device->ble == FIXED) {
|
if (dc_iostream_get_transport (device->iostream) == DC_TRANSPORT_BLE) {
|
||||||
return dc_iostream_close (device->iostream);
|
return dc_iostream_close (device->iostream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -734,7 +575,7 @@ mares_iconhd_device_read (dc_device_t *abstract, unsigned int address, unsigned
|
|||||||
len = device->packetsize;
|
len = device->packetsize;
|
||||||
|
|
||||||
// Read the packet.
|
// Read the packet.
|
||||||
unsigned char command[] = {
|
unsigned char command[] = {CMD_READ, CMD_READ ^ XOR,
|
||||||
(address ) & 0xFF,
|
(address ) & 0xFF,
|
||||||
(address >> 8) & 0xFF,
|
(address >> 8) & 0xFF,
|
||||||
(address >> 16) & 0xFF,
|
(address >> 16) & 0xFF,
|
||||||
@ -743,7 +584,7 @@ mares_iconhd_device_read (dc_device_t *abstract, unsigned int address, unsigned
|
|||||||
(len >> 8) & 0xFF,
|
(len >> 8) & 0xFF,
|
||||||
(len >> 16) & 0xFF,
|
(len >> 16) & 0xFF,
|
||||||
(len >> 24) & 0xFF};
|
(len >> 24) & 0xFF};
|
||||||
rc = mares_iconhd_transfer (device, CMD_READ, command, sizeof (command), data, len, NULL);
|
rc = mares_iconhd_transfer (device, command, sizeof (command), data, len);
|
||||||
if (rc != DC_STATUS_SUCCESS)
|
if (rc != DC_STATUS_SUCCESS)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -800,21 +641,6 @@ mares_iconhd_device_foreach_raw (dc_device_t *abstract, dc_dive_callback_t callb
|
|||||||
|
|
||||||
const mares_iconhd_layout_t *layout = device->layout;
|
const mares_iconhd_layout_t *layout = device->layout;
|
||||||
|
|
||||||
// Read the serial number.
|
|
||||||
unsigned char serial[4] = {0};
|
|
||||||
rc = mares_iconhd_device_read (abstract, 0x0C, serial, sizeof (serial));
|
|
||||||
if (rc != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to read the memory.");
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit a device info event.
|
|
||||||
dc_event_devinfo_t devinfo;
|
|
||||||
devinfo.model = device->model;
|
|
||||||
devinfo.firmware = 0;
|
|
||||||
devinfo.serial = array_uint32_le (serial);
|
|
||||||
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);
|
|
||||||
|
|
||||||
// Enable progress notifications.
|
// Enable progress notifications.
|
||||||
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
|
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
|
||||||
progress.maximum = layout->rb_profile_end - layout->rb_profile_begin;
|
progress.maximum = layout->rb_profile_end - layout->rb_profile_begin;
|
||||||
@ -864,7 +690,7 @@ mares_iconhd_device_foreach_raw (dc_device_t *abstract, dc_dive_callback_t callb
|
|||||||
|
|
||||||
// Create the ringbuffer stream.
|
// Create the ringbuffer stream.
|
||||||
dc_rbstream_t *rbstream = NULL;
|
dc_rbstream_t *rbstream = NULL;
|
||||||
rc = dc_rbstream_new (&rbstream, abstract, 1, device->packetsize, layout->rb_profile_begin, layout->rb_profile_end, eop, DC_RBSTREAM_BACKWARD);
|
rc = dc_rbstream_new (&rbstream, abstract, 1, device->packetsize, layout->rb_profile_begin, layout->rb_profile_end, eop);
|
||||||
if (rc != DC_STATUS_SUCCESS) {
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
ERROR (abstract->context, "Failed to create the ringbuffer stream.");
|
ERROR (abstract->context, "Failed to create the ringbuffer stream.");
|
||||||
return rc;
|
return rc;
|
||||||
@ -891,7 +717,7 @@ mares_iconhd_device_foreach_raw (dc_device_t *abstract, dc_dive_callback_t callb
|
|||||||
|
|
||||||
// Get the number of samples in the profile data.
|
// Get the number of samples in the profile data.
|
||||||
unsigned int type = 0, nsamples = 0;
|
unsigned int type = 0, nsamples = 0;
|
||||||
if (ISSMART(model)) {
|
if (model == SMART || model == SMARTAPNEA || model == SMARTAIR) {
|
||||||
type = array_uint16_le (buffer + offset - header + 2);
|
type = array_uint16_le (buffer + offset - header + 2);
|
||||||
nsamples = array_uint16_le (buffer + offset - header + 0);
|
nsamples = array_uint16_le (buffer + offset - header + 0);
|
||||||
} else {
|
} else {
|
||||||
@ -1020,33 +846,6 @@ mares_iconhd_device_foreach_object (dc_device_t *abstract, dc_dive_callback_t ca
|
|||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the serial number.
|
|
||||||
rc = mares_iconhd_read_object (device, NULL, buffer, OBJ_DEVICE, OBJ_DEVICE_SERIAL);
|
|
||||||
if (rc != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to read the serial number.");
|
|
||||||
dc_buffer_free (buffer);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dc_buffer_get_size (buffer) < 16) {
|
|
||||||
ERROR (abstract->context, "Unexpected number of bytes received (" DC_PRINTF_SIZE ").",
|
|
||||||
dc_buffer_get_size (buffer));
|
|
||||||
dc_buffer_free (buffer);
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int serial = array_convert_str2num (dc_buffer_get_data (buffer) + 10, 6);
|
|
||||||
|
|
||||||
// Emit a device info event.
|
|
||||||
dc_event_devinfo_t devinfo;
|
|
||||||
devinfo.model = device->model;
|
|
||||||
devinfo.firmware = 0;
|
|
||||||
devinfo.serial = serial;
|
|
||||||
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);
|
|
||||||
|
|
||||||
// Erase the buffer.
|
|
||||||
dc_buffer_clear (buffer);
|
|
||||||
|
|
||||||
// Read the number of dives.
|
// Read the number of dives.
|
||||||
rc = mares_iconhd_read_object (device, NULL, buffer, OBJ_LOGBOOK, OBJ_LOGBOOK_COUNT);
|
rc = mares_iconhd_read_object (device, NULL, buffer, OBJ_LOGBOOK, OBJ_LOGBOOK_COUNT);
|
||||||
if (rc != DC_STATUS_SUCCESS) {
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
@ -1109,6 +908,7 @@ mares_iconhd_device_foreach_object (dc_device_t *abstract, dc_dive_callback_t ca
|
|||||||
static dc_status_t
|
static dc_status_t
|
||||||
mares_iconhd_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata)
|
mares_iconhd_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata)
|
||||||
{
|
{
|
||||||
|
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||||
mares_iconhd_device_t *device = (mares_iconhd_device_t *) abstract;
|
mares_iconhd_device_t *device = (mares_iconhd_device_t *) abstract;
|
||||||
|
|
||||||
// Emit a vendor event.
|
// Emit a vendor event.
|
||||||
@ -1117,7 +917,22 @@ mares_iconhd_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback,
|
|||||||
vendor.size = sizeof (device->version);
|
vendor.size = sizeof (device->version);
|
||||||
device_event_emit (abstract, DC_EVENT_VENDOR, &vendor);
|
device_event_emit (abstract, DC_EVENT_VENDOR, &vendor);
|
||||||
|
|
||||||
if (ISGENIUS(device->model)) {
|
// Read the serial number.
|
||||||
|
unsigned char serial[4] = {0};
|
||||||
|
rc = mares_iconhd_device_read (abstract, 0x0C, serial, sizeof (serial));
|
||||||
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
|
ERROR (abstract->context, "Failed to read the memory.");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit a device info event.
|
||||||
|
dc_event_devinfo_t devinfo;
|
||||||
|
devinfo.model = device->model;
|
||||||
|
devinfo.firmware = 0;
|
||||||
|
devinfo.serial = array_uint32_le (serial);
|
||||||
|
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);
|
||||||
|
|
||||||
|
if (device->model == GENIUS || device->model == HORIZON) {
|
||||||
return mares_iconhd_device_foreach_object (abstract, callback, userdata);
|
return mares_iconhd_device_foreach_object (abstract, callback, userdata);
|
||||||
} else {
|
} else {
|
||||||
return mares_iconhd_device_foreach_raw (abstract, callback, userdata);
|
return mares_iconhd_device_foreach_raw (abstract, callback, userdata);
|
||||||
|
|||||||
@ -32,10 +32,10 @@ extern "C" {
|
|||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
mares_iconhd_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
mares_iconhd_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
mares_iconhd_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
mares_iconhd_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,23 +45,6 @@
|
|||||||
#define QUADAIR 0x23
|
#define QUADAIR 0x23
|
||||||
#define SMARTAIR 0x24
|
#define SMARTAIR 0x24
|
||||||
#define HORIZON 0x2C
|
#define HORIZON 0x2C
|
||||||
#define PUCKAIR2 0x2D
|
|
||||||
#define SIRIUS 0x2F
|
|
||||||
#define QUADCI 0x31
|
|
||||||
#define PUCK4 0x35
|
|
||||||
|
|
||||||
#define ISSMART(model) ( \
|
|
||||||
(model) == SMART || \
|
|
||||||
(model) == SMARTAPNEA || \
|
|
||||||
(model) == SMARTAIR)
|
|
||||||
|
|
||||||
#define ISGENIUS(model) ( \
|
|
||||||
(model) == GENIUS || \
|
|
||||||
(model) == HORIZON || \
|
|
||||||
(model) == PUCKAIR2 || \
|
|
||||||
(model) == SIRIUS || \
|
|
||||||
(model) == QUADCI || \
|
|
||||||
(model) == PUCK4)
|
|
||||||
|
|
||||||
#define NGASMIXES_ICONHD 3
|
#define NGASMIXES_ICONHD 3
|
||||||
#define NGASMIXES_GENIUS 5
|
#define NGASMIXES_GENIUS 5
|
||||||
@ -281,6 +264,7 @@ static const mares_iconhd_layout_t horizon = {
|
|||||||
0x54 + 8, /* tanks */
|
0x54 + 8, /* tanks */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static dc_status_t mares_iconhd_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t mares_iconhd_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t mares_iconhd_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -288,6 +272,7 @@ static dc_status_t mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, d
|
|||||||
static const dc_parser_vtable_t mares_iconhd_parser_vtable = {
|
static const dc_parser_vtable_t mares_iconhd_parser_vtable = {
|
||||||
sizeof(mares_iconhd_parser_t),
|
sizeof(mares_iconhd_parser_t),
|
||||||
DC_FAMILY_MARES_ICONHD,
|
DC_FAMILY_MARES_ICONHD,
|
||||||
|
mares_iconhd_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -297,6 +282,28 @@ static const dc_parser_vtable_t mares_iconhd_parser_vtable = {
|
|||||||
NULL /* destroy */
|
NULL /* destroy */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
mares_genius_isvalid (const unsigned char data[], size_t size, unsigned int type)
|
||||||
|
{
|
||||||
|
if (size < 10) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int head = array_uint32_be(data);
|
||||||
|
unsigned int tail = array_uint32_be(data + size - 4);
|
||||||
|
if (head != type || tail != type) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short crc = array_uint16_le(data + size - 6);
|
||||||
|
unsigned short ccrc = checksum_crc16_ccitt(data + 4, size - 10, 0x0000, 0x0000);
|
||||||
|
if (crc != ccrc) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
mares_iconhd_cache (mares_iconhd_parser_t *parser)
|
mares_iconhd_cache (mares_iconhd_parser_t *parser)
|
||||||
{
|
{
|
||||||
@ -327,7 +334,7 @@ mares_iconhd_cache (mares_iconhd_parser_t *parser)
|
|||||||
|
|
||||||
// Get the number of samples in the profile data.
|
// Get the number of samples in the profile data.
|
||||||
unsigned int type = 0, nsamples = 0;
|
unsigned int type = 0, nsamples = 0;
|
||||||
if (ISSMART (parser->model)) {
|
if (parser->model == SMART || parser->model == SMARTAPNEA || parser->model == SMARTAIR) {
|
||||||
type = array_uint16_le (data + length - header + 2);
|
type = array_uint16_le (data + length - header + 2);
|
||||||
nsamples = array_uint16_le (data + length - header + 0);
|
nsamples = array_uint16_le (data + length - header + 0);
|
||||||
} else {
|
} else {
|
||||||
@ -382,7 +389,7 @@ mares_iconhd_cache (mares_iconhd_parser_t *parser)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const unsigned char *p = data + length - headersize;
|
const unsigned char *p = data + length - headersize;
|
||||||
if (!ISSMART(parser->model)) {
|
if (parser->model != SMART && parser->model != SMARTAPNEA && parser->model != SMARTAIR) {
|
||||||
p += 4;
|
p += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,12 +401,12 @@ mares_iconhd_cache (mares_iconhd_parser_t *parser)
|
|||||||
unsigned int samplerate = 0;
|
unsigned int samplerate = 0;
|
||||||
if (parser->model == SMARTAPNEA) {
|
if (parser->model == SMARTAPNEA) {
|
||||||
unsigned int idx = (settings & 0x0600) >> 9;
|
unsigned int idx = (settings & 0x0600) >> 9;
|
||||||
|
interval = 1;
|
||||||
samplerate = 1 << idx;
|
samplerate = 1 << idx;
|
||||||
interval = 1000 / samplerate;
|
|
||||||
} else {
|
} else {
|
||||||
const unsigned int intervals[] = {1, 5, 10, 20};
|
const unsigned int intervals[] = {1, 5, 10, 20};
|
||||||
unsigned int idx = (settings & 0x0C00) >> 10;
|
unsigned int idx = (settings & 0x0C00) >> 10;
|
||||||
interval = intervals[idx] * 1000;
|
interval = intervals[idx];
|
||||||
samplerate = 1;
|
samplerate = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -540,22 +547,30 @@ mares_genius_cache (mares_iconhd_parser_t *parser)
|
|||||||
// Get the dive mode.
|
// Get the dive mode.
|
||||||
unsigned int mode = settings & 0xF;
|
unsigned int mode = settings & 0xF;
|
||||||
|
|
||||||
|
// Get the sample size.
|
||||||
|
unsigned int samplesize = logformat == 1 ? SDPT_SIZE: DPRS_SIZE;
|
||||||
|
|
||||||
|
// Calculate the total number of bytes for this dive.
|
||||||
|
unsigned int nbytes = headersize + 4 + DSTR_SIZE + TISS_SIZE + nsamples * samplesize + (nsamples / 4) * AIRS_SIZE + DEND_SIZE;
|
||||||
|
if (nbytes > size) {
|
||||||
|
ERROR (abstract->context, "Buffer overflow detected!");
|
||||||
|
return DC_STATUS_DATAFORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the profile type and version.
|
||||||
|
unsigned int profile_type = array_uint16_le (data + headersize);
|
||||||
|
unsigned int profile_minor = data[headersize + 2];
|
||||||
|
unsigned int profile_major = data[headersize + 3];
|
||||||
|
|
||||||
// Get the surface timeout setting (in minutes).
|
// Get the surface timeout setting (in minutes).
|
||||||
// For older firmware versions the value is hardcoded to 3 minutes, but
|
// For older firmware versions the value is hardcoded to 3 minutes, but
|
||||||
// starting with the newer v01.02.00 firmware the value is configurable and
|
// starting with the newer v01.02.00 firmware the value is configurable and
|
||||||
// stored in the settings. To detect whether the setting is available, we
|
// stored in the settings. To detect whether the setting is available, we
|
||||||
// need to check the profile version instead of the header version.
|
// need to check the profile version instead of the header version.
|
||||||
unsigned int surftime = 3;
|
unsigned int surftime = 3;
|
||||||
if (headersize + 4 <= size) {
|
if (profile_type == 0 &&
|
||||||
// Get the profile type and version.
|
OBJVERSION(profile_major,profile_minor) >= OBJVERSION(1,0)) {
|
||||||
unsigned int profile_type = array_uint16_le (data + headersize);
|
surftime = (settings >> 13) & 0x3F;
|
||||||
unsigned int profile_minor = data[headersize + 2];
|
|
||||||
unsigned int profile_major = data[headersize + 3];
|
|
||||||
|
|
||||||
if (profile_type == 0 &&
|
|
||||||
OBJVERSION(profile_major,profile_minor) >= OBJVERSION(1,0)) {
|
|
||||||
surftime = (settings >> 13) & 0x3F;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gas mixes and tanks.
|
// Gas mixes and tanks.
|
||||||
@ -606,11 +621,11 @@ mares_genius_cache (mares_iconhd_parser_t *parser)
|
|||||||
parser->logformat = logformat;
|
parser->logformat = logformat;
|
||||||
parser->mode = mode;
|
parser->mode = mode;
|
||||||
parser->nsamples = nsamples;
|
parser->nsamples = nsamples;
|
||||||
parser->samplesize = 0;
|
parser->samplesize = samplesize;
|
||||||
parser->headersize = headersize;
|
parser->headersize = headersize;
|
||||||
parser->settings = settings;
|
parser->settings = settings;
|
||||||
parser->surftime = surftime * 60;
|
parser->surftime = surftime * 60;
|
||||||
parser->interval = 5000;
|
parser->interval = 5;
|
||||||
parser->samplerate = 1;
|
parser->samplerate = 1;
|
||||||
parser->ntanks = ntanks;
|
parser->ntanks = ntanks;
|
||||||
parser->ngasmixes = ngasmixes;
|
parser->ngasmixes = ngasmixes;
|
||||||
@ -633,7 +648,7 @@ mares_iconhd_parser_cache (mares_iconhd_parser_t *parser)
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ISGENIUS(parser->model)) {
|
if (parser->model == GENIUS || parser->model == HORIZON) {
|
||||||
return mares_genius_cache (parser);
|
return mares_genius_cache (parser);
|
||||||
} else {
|
} else {
|
||||||
return mares_iconhd_cache (parser);
|
return mares_iconhd_cache (parser);
|
||||||
@ -641,7 +656,7 @@ mares_iconhd_parser_cache (mares_iconhd_parser_t *parser)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
mares_iconhd_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
mares_iconhd_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||||
{
|
{
|
||||||
mares_iconhd_parser_t *parser = NULL;
|
mares_iconhd_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -649,7 +664,7 @@ mares_iconhd_parser_create (dc_parser_t **out, dc_context_t *context, const unsi
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (mares_iconhd_parser_t *) dc_parser_allocate (context, &mares_iconhd_parser_vtable, data, size);
|
parser = (mares_iconhd_parser_t *) dc_parser_allocate (context, &mares_iconhd_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -659,7 +674,7 @@ mares_iconhd_parser_create (dc_parser_t **out, dc_context_t *context, const unsi
|
|||||||
parser->model = model;
|
parser->model = model;
|
||||||
parser->cached = 0;
|
parser->cached = 0;
|
||||||
parser->logformat = 0;
|
parser->logformat = 0;
|
||||||
parser->mode = ISGENIUS(model) ? GENIUS_AIR : ICONHD_AIR;
|
parser->mode = (model == GENIUS || model == HORIZON) ? GENIUS_AIR : ICONHD_AIR;
|
||||||
parser->nsamples = 0;
|
parser->nsamples = 0;
|
||||||
parser->samplesize = 0;
|
parser->samplesize = 0;
|
||||||
parser->headersize = 0;
|
parser->headersize = 0;
|
||||||
@ -686,6 +701,41 @@ mares_iconhd_parser_create (dc_parser_t **out, dc_context_t *context, const unsi
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
mares_iconhd_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
mares_iconhd_parser_t *parser = (mares_iconhd_parser_t *) abstract;
|
||||||
|
|
||||||
|
// Reset the cache.
|
||||||
|
parser->cached = 0;
|
||||||
|
parser->logformat = 0;
|
||||||
|
parser->mode = (parser->model == GENIUS || parser->model == HORIZON) ? GENIUS_AIR : ICONHD_AIR;
|
||||||
|
parser->nsamples = 0;
|
||||||
|
parser->samplesize = 0;
|
||||||
|
parser->headersize = 0;
|
||||||
|
parser->settings = 0;
|
||||||
|
parser->surftime = 0;
|
||||||
|
parser->interval = 0;
|
||||||
|
parser->samplerate = 0;
|
||||||
|
parser->ntanks = 0;
|
||||||
|
parser->ngasmixes = 0;
|
||||||
|
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||||
|
parser->gasmix[i].oxygen = 0;
|
||||||
|
parser->gasmix[i].helium = 0;
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i < NTANKS; ++i) {
|
||||||
|
parser->tank[i].volume = 0;
|
||||||
|
parser->tank[i].workpressure = 0;
|
||||||
|
parser->tank[i].beginpressure = 0;
|
||||||
|
parser->tank[i].endpressure = 0;
|
||||||
|
}
|
||||||
|
parser->layout = NULL;
|
||||||
|
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
mares_iconhd_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
mares_iconhd_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -698,9 +748,9 @@ mares_iconhd_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime
|
|||||||
|
|
||||||
// Pointer to the header data.
|
// Pointer to the header data.
|
||||||
const unsigned char *p = abstract->data;
|
const unsigned char *p = abstract->data;
|
||||||
if (!ISGENIUS(parser->model)) {
|
if (parser->model != GENIUS && parser->model != HORIZON) {
|
||||||
p += abstract->size - parser->headersize;
|
p += abstract->size - parser->headersize;
|
||||||
if (!ISSMART(parser->model)) {
|
if (parser->model != SMART && parser->model != SMARTAPNEA && parser->model != SMARTAIR) {
|
||||||
p += 4;
|
p += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -709,7 +759,7 @@ mares_iconhd_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime
|
|||||||
p += parser->layout->datetime;
|
p += parser->layout->datetime;
|
||||||
|
|
||||||
if (datetime) {
|
if (datetime) {
|
||||||
if (ISGENIUS(parser->model)) {
|
if (parser->model == GENIUS || parser->model == HORIZON) {
|
||||||
unsigned int timestamp = array_uint32_le (p);
|
unsigned int timestamp = array_uint32_le (p);
|
||||||
datetime->hour = (timestamp ) & 0x1F;
|
datetime->hour = (timestamp ) & 0x1F;
|
||||||
datetime->minute = (timestamp >> 5) & 0x3F;
|
datetime->minute = (timestamp >> 5) & 0x3F;
|
||||||
@ -744,9 +794,9 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
|
|||||||
|
|
||||||
// Pointer to the header data.
|
// Pointer to the header data.
|
||||||
const unsigned char *p = abstract->data;
|
const unsigned char *p = abstract->data;
|
||||||
if (!ISGENIUS(parser->model)) {
|
if (parser->model != GENIUS && parser->model != HORIZON) {
|
||||||
p += abstract->size - parser->headersize;
|
p += abstract->size - parser->headersize;
|
||||||
if (!ISSMART(parser->model)) {
|
if (parser->model != SMART && parser->model != SMARTAPNEA && parser->model != SMARTAIR) {
|
||||||
p += 4;
|
p += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -757,7 +807,7 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
|
|||||||
extra = 8;
|
extra = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int metric = ISGENIUS(parser->model) ?
|
unsigned int metric = (parser->model == GENIUS || parser->model == HORIZON) ?
|
||||||
p[0x34 + extra] : parser->settings & 0x0100;
|
p[0x34 + extra] : parser->settings & 0x0100;
|
||||||
|
|
||||||
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
|
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
|
||||||
@ -770,7 +820,7 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
|
|||||||
if (parser->layout->divetime != UNSUPPORTED) {
|
if (parser->layout->divetime != UNSUPPORTED) {
|
||||||
*((unsigned int *) value) = array_uint16_le (p + parser->layout->divetime);
|
*((unsigned int *) value) = array_uint16_le (p + parser->layout->divetime);
|
||||||
} else {
|
} else {
|
||||||
*((unsigned int *) value) = parser->nsamples * parser->interval / 1000 - parser->surftime;
|
*((unsigned int *) value) = parser->nsamples * parser->interval - parser->surftime;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_MAXDEPTH:
|
case DC_FIELD_MAXDEPTH:
|
||||||
@ -780,7 +830,6 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
|
|||||||
*((unsigned int *) value) = parser->ngasmixes;
|
*((unsigned int *) value) = parser->ngasmixes;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
||||||
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
||||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||||
@ -808,13 +857,12 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
|
|||||||
} else {
|
} else {
|
||||||
tank->gasmix = DC_GASMIX_UNKNOWN;
|
tank->gasmix = DC_GASMIX_UNKNOWN;
|
||||||
}
|
}
|
||||||
tank->usage = DC_USAGE_NONE;
|
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_ATMOSPHERIC:
|
case DC_FIELD_ATMOSPHERIC:
|
||||||
*((double *) value) = array_uint16_le (p + parser->layout->atmospheric) / (1000.0 * parser->layout->atmospheric_divisor);
|
*((double *) value) = array_uint16_le (p + parser->layout->atmospheric) / (1000.0 * parser->layout->atmospheric_divisor);
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_SALINITY:
|
case DC_FIELD_SALINITY:
|
||||||
if (ISGENIUS(parser->model)) {
|
if (parser->model == GENIUS || parser->model == HORIZON) {
|
||||||
unsigned int salinity = (parser->settings >> 5) & 0x03;
|
unsigned int salinity = (parser->settings >> 5) & 0x03;
|
||||||
switch (salinity) {
|
switch (salinity) {
|
||||||
case WATER_FRESH:
|
case WATER_FRESH:
|
||||||
@ -856,7 +904,7 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
|
|||||||
*((double *) value) = (signed short) array_uint16_le (p + parser->layout->temperature_max) / 10.0;
|
*((double *) value) = (signed short) array_uint16_le (p + parser->layout->temperature_max) / 10.0;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_DIVEMODE:
|
case DC_FIELD_DIVEMODE:
|
||||||
if (ISGENIUS(parser->model)) {
|
if (parser->model == GENIUS || parser->model == HORIZON) {
|
||||||
switch (parser->mode) {
|
switch (parser->mode) {
|
||||||
case GENIUS_AIR:
|
case GENIUS_AIR:
|
||||||
case GENIUS_NITROX_SINGLE:
|
case GENIUS_NITROX_SINGLE:
|
||||||
@ -904,16 +952,64 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
|
|||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
mares_iconhd_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
|
mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
|
||||||
{
|
{
|
||||||
mares_iconhd_parser_t *parser = (mares_iconhd_parser_t *) abstract;
|
mares_iconhd_parser_t *parser = (mares_iconhd_parser_t *) abstract;
|
||||||
|
|
||||||
|
// Cache the parser data.
|
||||||
|
dc_status_t rc = mares_iconhd_parser_cache (parser);
|
||||||
|
if (rc != DC_STATUS_SUCCESS)
|
||||||
|
return rc;
|
||||||
|
|
||||||
const unsigned char *data = abstract->data;
|
const unsigned char *data = abstract->data;
|
||||||
|
|
||||||
|
if (parser->samplerate > 1) {
|
||||||
|
// The Smart Apnea supports multiple samples per second
|
||||||
|
// (e.g. 2, 4 or 8). Since our smallest unit of time is one
|
||||||
|
// second, we can't represent this, and the extra samples
|
||||||
|
// will get dropped.
|
||||||
|
WARNING(abstract->context, "Multiple samples per second are not supported!");
|
||||||
|
}
|
||||||
|
|
||||||
// Previous gas mix - initialize with impossible value
|
// Previous gas mix - initialize with impossible value
|
||||||
unsigned int gasmix_previous = 0xFFFFFFFF;
|
unsigned int gasmix_previous = 0xFFFFFFFF;
|
||||||
|
|
||||||
unsigned int offset = 4;
|
unsigned int offset = 4;
|
||||||
unsigned int marker = 0;
|
unsigned int marker = 0;
|
||||||
|
if (parser->model == GENIUS || parser->model == HORIZON) {
|
||||||
|
// Skip the dive header.
|
||||||
|
data += parser->headersize;
|
||||||
|
|
||||||
|
// Check the profile type and version.
|
||||||
|
unsigned int type = array_uint16_le (data);
|
||||||
|
unsigned int minor = data[2];
|
||||||
|
unsigned int major = data[3];
|
||||||
|
if (type > 1 ||
|
||||||
|
(type == 0 && OBJVERSION(major,minor) > OBJVERSION(1,0)) ||
|
||||||
|
(type == 1 && OBJVERSION(major,minor) > OBJVERSION(0,2))) {
|
||||||
|
ERROR (abstract->context, "Unsupported object type (%u) or version (%u.%u).",
|
||||||
|
type, major, minor);
|
||||||
|
return DC_STATUS_DATAFORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip the DSTR record.
|
||||||
|
if (!mares_genius_isvalid (data + offset, DSTR_SIZE, DSTR_TYPE)) {
|
||||||
|
ERROR (abstract->context, "Invalid DSTR record.");
|
||||||
|
return DC_STATUS_DATAFORMAT;
|
||||||
|
}
|
||||||
|
offset += DSTR_SIZE;
|
||||||
|
|
||||||
|
// Skip the TISS record.
|
||||||
|
if (!mares_genius_isvalid (data + offset, TISS_SIZE, TISS_TYPE)) {
|
||||||
|
ERROR (abstract->context, "Invalid TISS record.");
|
||||||
|
return DC_STATUS_DATAFORMAT;
|
||||||
|
}
|
||||||
|
offset += TISS_SIZE;
|
||||||
|
|
||||||
|
// Size of the record type marker.
|
||||||
|
marker = 4;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int time = 0;
|
unsigned int time = 0;
|
||||||
unsigned int nsamples = 0;
|
unsigned int nsamples = 0;
|
||||||
while (nsamples < parser->nsamples) {
|
while (nsamples < parser->nsamples) {
|
||||||
@ -925,73 +1021,118 @@ mares_iconhd_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void
|
|||||||
unsigned int surftime = array_uint16_le (data + offset + 4);
|
unsigned int surftime = array_uint16_le (data + offset + 4);
|
||||||
|
|
||||||
// Surface Time (seconds).
|
// Surface Time (seconds).
|
||||||
time += surftime * 1000;
|
time += surftime;
|
||||||
sample.time = time;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Surface Depth (0 m).
|
// Surface Depth (0 m).
|
||||||
sample.depth = 0.0;
|
sample.depth = 0.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
offset += parser->samplesize;
|
offset += parser->samplesize;
|
||||||
nsamples++;
|
nsamples++;
|
||||||
|
|
||||||
unsigned int count = divetime * parser->samplerate;
|
for (unsigned int i = 0; i < divetime; ++i) {
|
||||||
for (unsigned int i = 0; i < count; ++i) {
|
|
||||||
// Time (seconds).
|
// Time (seconds).
|
||||||
time += parser->interval;
|
time += parser->interval;
|
||||||
sample.time = time;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Depth (1/10 m).
|
// Depth (1/10 m).
|
||||||
unsigned int depth = array_uint16_le (data + offset);
|
unsigned int depth = array_uint16_le (data + offset);
|
||||||
sample.depth = depth / 10.0;
|
sample.depth = depth / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
offset += 2;
|
offset += 2 * parser->samplerate;
|
||||||
}
|
}
|
||||||
} else if (parser->mode == ICONHD_FREEDIVE) {
|
} else if (parser->model != GENIUS && parser->model != HORIZON && parser->mode == ICONHD_FREEDIVE) {
|
||||||
unsigned int maxdepth = array_uint16_le (data + offset + 0);
|
unsigned int maxdepth = array_uint16_le (data + offset + 0);
|
||||||
unsigned int divetime = array_uint16_le (data + offset + 2);
|
unsigned int divetime = array_uint16_le (data + offset + 2);
|
||||||
unsigned int surftime = array_uint16_le (data + offset + 4);
|
unsigned int surftime = array_uint16_le (data + offset + 4);
|
||||||
|
|
||||||
// Surface Time (seconds).
|
// Surface Time (seconds).
|
||||||
time += surftime * 1000;
|
time += surftime;
|
||||||
sample.time = time;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Surface Depth (0 m).
|
// Surface Depth (0 m).
|
||||||
sample.depth = 0.0;
|
sample.depth = 0.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
// Dive Time (seconds).
|
// Dive Time (seconds).
|
||||||
time += divetime * 1000;
|
time += divetime;
|
||||||
sample.time = time;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Maximum Depth (1/10 m).
|
// Maximum Depth (1/10 m).
|
||||||
sample.depth = maxdepth / 10.0;
|
sample.depth = maxdepth / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
offset += parser->samplesize;
|
offset += parser->samplesize;
|
||||||
nsamples++;
|
nsamples++;
|
||||||
} else {
|
} else {
|
||||||
unsigned int depth = array_uint16_le (data + offset + 0);
|
unsigned int depth = 0, temperature = 0;
|
||||||
unsigned int temperature = array_uint16_le (data + offset + 2) & 0x0FFF;
|
unsigned int gasmix = 0, alarms = 0;
|
||||||
unsigned int gasmix = (data[offset + 3] & 0xF0) >> 4;
|
unsigned int decostop = 0, decodepth = 0, decotime = 0, tts = 0;
|
||||||
|
unsigned int bookmark = 0;
|
||||||
|
if (parser->model == GENIUS || parser->model == HORIZON) {
|
||||||
|
if (parser->logformat == 1) {
|
||||||
|
if (!mares_genius_isvalid (data + offset, SDPT_SIZE, SDPT_TYPE)) {
|
||||||
|
ERROR (abstract->context, "Invalid SDPT record.");
|
||||||
|
return DC_STATUS_DATAFORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int misc = 0, deco = 0;
|
||||||
|
depth = array_uint16_le (data + offset + marker + 2);
|
||||||
|
temperature = array_uint16_le (data + offset + marker + 6);
|
||||||
|
alarms = array_uint32_le (data + offset + marker + 0x14);
|
||||||
|
misc = array_uint32_le (data + offset + marker + 0x18);
|
||||||
|
deco = array_uint32_le (data + offset + marker + 0x1C);
|
||||||
|
bookmark = (misc >> 2) & 0x0F;
|
||||||
|
gasmix = (misc >> 6) & 0x0F;
|
||||||
|
decostop = (misc >> 10) & 0x01;
|
||||||
|
if (decostop) {
|
||||||
|
decodepth = (deco >> 3) & 0x7F;
|
||||||
|
decotime = (deco >> 10) & 0xFF;
|
||||||
|
tts = (deco >> 18) & 0x3FFF;
|
||||||
|
} else {
|
||||||
|
decotime = deco & 0xFF;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!mares_genius_isvalid (data + offset, DPRS_SIZE, DPRS_TYPE)) {
|
||||||
|
ERROR (abstract->context, "Invalid DPRS record.");
|
||||||
|
return DC_STATUS_DATAFORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int misc = 0;
|
||||||
|
depth = array_uint16_le (data + offset + marker + 0);
|
||||||
|
temperature = array_uint16_le (data + offset + marker + 4);
|
||||||
|
decotime = array_uint16_le (data + offset + marker + 0x0A);
|
||||||
|
alarms = array_uint32_le (data + offset + marker + 0x0C);
|
||||||
|
misc = array_uint32_le (data + offset + marker + 0x14);
|
||||||
|
bookmark = (misc >> 2) & 0x0F;
|
||||||
|
gasmix = (misc >> 6) & 0x0F;
|
||||||
|
decostop = (misc >> 18) & 0x01;
|
||||||
|
decodepth = (misc >> 19) & 0x7F;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
depth = array_uint16_le (data + offset + 0);
|
||||||
|
temperature = array_uint16_le (data + offset + 2) & 0x0FFF;
|
||||||
|
gasmix = (data[offset + 3] & 0xF0) >> 4;
|
||||||
|
}
|
||||||
|
|
||||||
// Time (seconds).
|
// Time (seconds).
|
||||||
time += parser->interval;
|
time += parser->interval;
|
||||||
sample.time = time;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Depth (1/10 m).
|
// Depth (1/10 m).
|
||||||
sample.depth = depth / 10.0;
|
sample.depth = depth / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
// Temperature (1/10 °C).
|
// Temperature (1/10 °C).
|
||||||
sample.temperature = temperature / 10.0;
|
sample.temperature = temperature / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
|
|
||||||
// Current gas mix
|
// Current gas mix
|
||||||
if (parser->ngasmixes > 0) {
|
if (parser->ngasmixes > 0) {
|
||||||
@ -1001,264 +1142,95 @@ mares_iconhd_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void
|
|||||||
}
|
}
|
||||||
if (gasmix != gasmix_previous) {
|
if (gasmix != gasmix_previous) {
|
||||||
sample.gasmix = gasmix;
|
sample.gasmix = gasmix;
|
||||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
gasmix_previous = gasmix;
|
gasmix_previous = gasmix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bookmark
|
||||||
|
if (bookmark) {
|
||||||
|
sample.event.type = SAMPLE_EVENT_BOOKMARK;
|
||||||
|
sample.event.time = 0;
|
||||||
|
sample.event.flags = 0;
|
||||||
|
sample.event.value = bookmark;
|
||||||
|
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser->model == GENIUS || parser->model == HORIZON) {
|
||||||
|
// Deco stop / NDL.
|
||||||
|
if (decostop) {
|
||||||
|
sample.deco.type = DC_DECO_DECOSTOP;
|
||||||
|
sample.deco.depth = decodepth;
|
||||||
|
} else {
|
||||||
|
sample.deco.type = DC_DECO_NDL;
|
||||||
|
sample.deco.depth = 0.0;
|
||||||
|
}
|
||||||
|
sample.deco.time = decotime * 60;
|
||||||
|
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||||
|
|
||||||
|
// Alarms
|
||||||
|
for (unsigned int v = alarms, i = 0; v; v >>= 1, ++i) {
|
||||||
|
if ((v & 1) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (i) {
|
||||||
|
case ALARM_FAST_ASCENT:
|
||||||
|
case ALARM_UNCONTROLLED_ASCENT:
|
||||||
|
sample.event.type = SAMPLE_EVENT_ASCENT;
|
||||||
|
break;
|
||||||
|
case ALARM_MISSED_DECO:
|
||||||
|
case ALARM_DIVE_VIOLATION_DECO:
|
||||||
|
sample.event.type = SAMPLE_EVENT_CEILING;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sample.event.type = SAMPLE_EVENT_NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sample.event.type != SAMPLE_EVENT_NONE) {
|
||||||
|
sample.event.time = 0;
|
||||||
|
sample.event.flags = 0;
|
||||||
|
sample.event.value = 0;
|
||||||
|
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
offset += parser->samplesize;
|
offset += parser->samplesize;
|
||||||
nsamples++;
|
nsamples++;
|
||||||
|
|
||||||
// Some extra data.
|
// Some extra data.
|
||||||
if (parser->layout->tanks != UNSUPPORTED && (nsamples % 4) == 0) {
|
if (parser->layout->tanks != UNSUPPORTED && (nsamples % 4) == 0) {
|
||||||
|
if ((parser->model == GENIUS || parser->model == HORIZON) &&
|
||||||
|
!mares_genius_isvalid (data + offset, AIRS_SIZE, AIRS_TYPE)) {
|
||||||
|
ERROR (abstract->context, "Invalid AIRS record.");
|
||||||
|
return DC_STATUS_DATAFORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
// Pressure (1/100 bar).
|
// Pressure (1/100 bar).
|
||||||
unsigned int pressure = array_uint16_le(data + offset + marker + 0);
|
unsigned int pressure = array_uint16_le(data + offset + marker + 0);
|
||||||
if (gasmix < parser->ntanks) {
|
if (gasmix < parser->ntanks) {
|
||||||
sample.pressure.tank = gasmix;
|
sample.pressure.tank = gasmix;
|
||||||
sample.pressure.value = pressure / 100.0;
|
sample.pressure.value = pressure / 100.0;
|
||||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||||
} else if (pressure != 0) {
|
} else if (pressure != 0) {
|
||||||
WARNING (abstract->context, "Invalid tank with non-zero pressure.");
|
WARNING (abstract->context, "Invalid tank with non-zero pressure.");
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += 8;
|
offset += (parser->model == GENIUS || parser->model == HORIZON) ? AIRS_SIZE : 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parser->model == GENIUS || parser->model == HORIZON) {
|
||||||
|
// Skip the DEND record.
|
||||||
|
if (!mares_genius_isvalid (data + offset, DEND_SIZE, DEND_TYPE)) {
|
||||||
|
ERROR (abstract->context, "Invalid DEND record.");
|
||||||
|
return DC_STATUS_DATAFORMAT;
|
||||||
|
}
|
||||||
|
offset += DEND_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
mares_genius_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
|
|
||||||
{
|
|
||||||
mares_iconhd_parser_t *parser = (mares_iconhd_parser_t *) abstract;
|
|
||||||
const unsigned char *data = abstract->data;
|
|
||||||
const unsigned int size = abstract->size;
|
|
||||||
|
|
||||||
// Previous gas mix - initialize with impossible value
|
|
||||||
unsigned int gasmix_previous = 0xFFFFFFFF;
|
|
||||||
unsigned int tank = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
// Skip the dive header.
|
|
||||||
unsigned int offset = parser->headersize;
|
|
||||||
|
|
||||||
if (offset + 4 > size) {
|
|
||||||
ERROR (abstract->context, "Buffer overflow detected!");
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the profile type and version.
|
|
||||||
unsigned int profile_type = array_uint16_le (data + offset);
|
|
||||||
unsigned int profile_minor = data[offset + 2];
|
|
||||||
unsigned int profile_major = data[offset + 3];
|
|
||||||
if (profile_type > 1 ||
|
|
||||||
(profile_type == 0 && OBJVERSION(profile_major,profile_minor) > OBJVERSION(1,0)) ||
|
|
||||||
(profile_type == 1 && OBJVERSION(profile_major,profile_minor) > OBJVERSION(0,2))) {
|
|
||||||
ERROR (abstract->context, "Unsupported object type (%u) or version (%u.%u).",
|
|
||||||
profile_type, profile_major, profile_minor);
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
}
|
|
||||||
offset += 4;
|
|
||||||
|
|
||||||
unsigned int time = 0;
|
|
||||||
unsigned int marker = 4;
|
|
||||||
while (offset < size) {
|
|
||||||
dc_sample_value_t sample = {0};
|
|
||||||
|
|
||||||
if (offset + 10 > size) {
|
|
||||||
ERROR (abstract->context, "Buffer overflow detected!");
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the record type and length.
|
|
||||||
unsigned int type = array_uint32_be(data + offset);
|
|
||||||
unsigned int length = 0;
|
|
||||||
switch (type) {
|
|
||||||
case DSTR_TYPE:
|
|
||||||
length = DSTR_SIZE;
|
|
||||||
break;
|
|
||||||
case TISS_TYPE:
|
|
||||||
length = TISS_SIZE;
|
|
||||||
break;
|
|
||||||
case DPRS_TYPE:
|
|
||||||
length = DPRS_SIZE;
|
|
||||||
break;
|
|
||||||
case SDPT_TYPE:
|
|
||||||
length = SDPT_SIZE;
|
|
||||||
break;
|
|
||||||
case AIRS_TYPE:
|
|
||||||
length = AIRS_SIZE;
|
|
||||||
break;
|
|
||||||
case DEND_TYPE:
|
|
||||||
length = DEND_SIZE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ERROR (abstract->context, "Unknown record type (%08x).", type);
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset + length > size) {
|
|
||||||
ERROR (abstract->context, "Buffer overflow detected!");
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int etype = array_uint32_be(data + offset + length - 4);
|
|
||||||
if (etype != type) {
|
|
||||||
ERROR (abstract->context, "Invalid record end type (%08x).", etype);
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned short crc = array_uint16_le(data + offset + length - 6);
|
|
||||||
unsigned short ccrc = checksum_crc16_ccitt(data + offset + 4, length - 10, 0x0000, 0x0000);
|
|
||||||
if (crc != ccrc) {
|
|
||||||
ERROR (abstract->context, "Invalid record checksum (%04x %04x).", crc, ccrc);
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == DPRS_TYPE || type == SDPT_TYPE) {
|
|
||||||
unsigned int depth = 0, temperature = 0;
|
|
||||||
unsigned int gasmix = 0, alarms = 0;
|
|
||||||
unsigned int decostop = 0, decodepth = 0, decotime = 0, tts = 0;
|
|
||||||
unsigned int bookmark = 0;
|
|
||||||
if (type == SDPT_TYPE) {
|
|
||||||
unsigned int misc = 0, deco = 0;
|
|
||||||
depth = array_uint16_le (data + offset + marker + 2);
|
|
||||||
temperature = array_uint16_le (data + offset + marker + 6);
|
|
||||||
alarms = array_uint32_le (data + offset + marker + 0x14);
|
|
||||||
misc = array_uint32_le (data + offset + marker + 0x18);
|
|
||||||
deco = array_uint32_le (data + offset + marker + 0x1C);
|
|
||||||
bookmark = (misc >> 2) & 0x0F;
|
|
||||||
gasmix = (misc >> 6) & 0x0F;
|
|
||||||
decostop = (misc >> 10) & 0x01;
|
|
||||||
if (decostop) {
|
|
||||||
decodepth = (deco >> 3) & 0x7F;
|
|
||||||
decotime = (deco >> 10) & 0xFF;
|
|
||||||
tts = (deco >> 18) & 0x3FFF;
|
|
||||||
} else {
|
|
||||||
decotime = deco & 0xFF;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unsigned int misc = 0;
|
|
||||||
depth = array_uint16_le (data + offset + marker + 0);
|
|
||||||
temperature = array_uint16_le (data + offset + marker + 4);
|
|
||||||
decotime = array_uint16_le (data + offset + marker + 0x0A);
|
|
||||||
alarms = array_uint32_le (data + offset + marker + 0x0C);
|
|
||||||
misc = array_uint32_le (data + offset + marker + 0x14);
|
|
||||||
bookmark = (misc >> 2) & 0x0F;
|
|
||||||
gasmix = (misc >> 6) & 0x0F;
|
|
||||||
decostop = (misc >> 18) & 0x01;
|
|
||||||
decodepth = (misc >> 19) & 0x7F;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Time (seconds).
|
|
||||||
time += parser->interval;
|
|
||||||
sample.time = time;
|
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
|
||||||
|
|
||||||
// Depth (1/10 m).
|
|
||||||
sample.depth = depth / 10.0;
|
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
|
||||||
|
|
||||||
// Temperature (1/10 °C).
|
|
||||||
sample.temperature = temperature / 10.0;
|
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
|
||||||
|
|
||||||
// Current gas mix
|
|
||||||
if (parser->ngasmixes > 0) {
|
|
||||||
if (gasmix >= parser->ngasmixes) {
|
|
||||||
ERROR (abstract->context, "Invalid gas mix index.");
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
}
|
|
||||||
if (gasmix != gasmix_previous) {
|
|
||||||
sample.gasmix = gasmix;
|
|
||||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
|
||||||
gasmix_previous = gasmix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Current tank
|
|
||||||
tank = gasmix;
|
|
||||||
|
|
||||||
// Bookmark
|
|
||||||
if (bookmark) {
|
|
||||||
sample.event.type = SAMPLE_EVENT_BOOKMARK;
|
|
||||||
sample.event.time = 0;
|
|
||||||
sample.event.flags = 0;
|
|
||||||
sample.event.value = bookmark;
|
|
||||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deco stop / NDL.
|
|
||||||
if (decostop) {
|
|
||||||
sample.deco.type = DC_DECO_DECOSTOP;
|
|
||||||
sample.deco.depth = decodepth;
|
|
||||||
} else {
|
|
||||||
sample.deco.type = DC_DECO_NDL;
|
|
||||||
sample.deco.depth = 0.0;
|
|
||||||
}
|
|
||||||
sample.deco.time = decotime * 60;
|
|
||||||
sample.deco.tts = tts;
|
|
||||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
|
||||||
|
|
||||||
// Alarms
|
|
||||||
for (unsigned int v = alarms, i = 0; v; v >>= 1, ++i) {
|
|
||||||
if ((v & 1) == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (i) {
|
|
||||||
case ALARM_FAST_ASCENT:
|
|
||||||
case ALARM_UNCONTROLLED_ASCENT:
|
|
||||||
sample.event.type = SAMPLE_EVENT_ASCENT;
|
|
||||||
break;
|
|
||||||
case ALARM_MISSED_DECO:
|
|
||||||
case ALARM_DIVE_VIOLATION_DECO:
|
|
||||||
sample.event.type = SAMPLE_EVENT_CEILING;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
sample.event.type = SAMPLE_EVENT_NONE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sample.event.type != SAMPLE_EVENT_NONE) {
|
|
||||||
sample.event.time = 0;
|
|
||||||
sample.event.flags = 0;
|
|
||||||
sample.event.value = 0;
|
|
||||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (type == AIRS_TYPE) {
|
|
||||||
// Pressure (1/100 bar).
|
|
||||||
unsigned int pressure = array_uint16_le(data + offset + marker + 0);
|
|
||||||
if (tank < parser->ntanks) {
|
|
||||||
sample.pressure.tank = tank;
|
|
||||||
sample.pressure.value = pressure / 100.0;
|
|
||||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
|
||||||
} else if (pressure != 0) {
|
|
||||||
WARNING (abstract->context, "Invalid tank with non-zero pressure.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
offset += length;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
|
|
||||||
{
|
|
||||||
mares_iconhd_parser_t *parser = (mares_iconhd_parser_t *) abstract;
|
|
||||||
|
|
||||||
// Cache the parser data.
|
|
||||||
dc_status_t rc = mares_iconhd_parser_cache (parser);
|
|
||||||
if (rc != DC_STATUS_SUCCESS)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
if (ISGENIUS(parser->model)) {
|
|
||||||
return mares_genius_foreach (abstract, callback, userdata);
|
|
||||||
} else {
|
|
||||||
return mares_iconhd_foreach (abstract, callback, userdata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -35,7 +35,7 @@ dc_status_t
|
|||||||
mares_nemo_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
mares_nemo_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
mares_nemo_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
mares_nemo_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,6 +59,7 @@ struct mares_nemo_parser_t {
|
|||||||
unsigned int extra;
|
unsigned int extra;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static dc_status_t mares_nemo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t mares_nemo_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t mares_nemo_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t mares_nemo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t mares_nemo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -66,6 +67,7 @@ static dc_status_t mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_
|
|||||||
static const dc_parser_vtable_t mares_nemo_parser_vtable = {
|
static const dc_parser_vtable_t mares_nemo_parser_vtable = {
|
||||||
sizeof(mares_nemo_parser_t),
|
sizeof(mares_nemo_parser_t),
|
||||||
DC_FAMILY_MARES_NEMO,
|
DC_FAMILY_MARES_NEMO,
|
||||||
|
mares_nemo_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -77,16 +79,15 @@ static const dc_parser_vtable_t mares_nemo_parser_vtable = {
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
mares_nemo_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
mares_nemo_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||||
{
|
{
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
|
||||||
mares_nemo_parser_t *parser = NULL;
|
mares_nemo_parser_t *parser = NULL;
|
||||||
|
|
||||||
if (out == NULL)
|
if (out == NULL)
|
||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (mares_nemo_parser_t *) dc_parser_allocate (context, &mares_nemo_parser_vtable, data, size);
|
parser = (mares_nemo_parser_t *) dc_parser_allocate (context, &mares_nemo_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -97,42 +98,70 @@ mares_nemo_parser_create (dc_parser_t **out, dc_context_t *context, const unsign
|
|||||||
if (model == NEMOWIDE || model == NEMOAIR || model == PUCK || model == PUCKAIR)
|
if (model == NEMOWIDE || model == NEMOAIR || model == PUCK || model == PUCKAIR)
|
||||||
freedive = GAUGE;
|
freedive = GAUGE;
|
||||||
|
|
||||||
if (size < 2 + 3) {
|
// Set the default values.
|
||||||
status = DC_STATUS_DATAFORMAT;
|
parser->model = model;
|
||||||
goto error_free;
|
parser->freedive = freedive;
|
||||||
}
|
parser->mode = AIR;
|
||||||
|
parser->length = 0;
|
||||||
|
parser->sample_count = 0;
|
||||||
|
parser->sample_size = 0;
|
||||||
|
parser->header = 0;
|
||||||
|
parser->extra = 0;
|
||||||
|
|
||||||
|
*out = (dc_parser_t*) parser;
|
||||||
|
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
mares_nemo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
mares_nemo_parser_t *parser = (mares_nemo_parser_t *) abstract;
|
||||||
|
|
||||||
|
// Clear the previous state.
|
||||||
|
parser->base.data = NULL;
|
||||||
|
parser->base.size = 0;
|
||||||
|
parser->mode = AIR;
|
||||||
|
parser->length = 0;
|
||||||
|
parser->sample_count = 0;
|
||||||
|
parser->sample_size = 0;
|
||||||
|
parser->header = 0;
|
||||||
|
parser->extra = 0;
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if (size < 2 + 3)
|
||||||
|
return DC_STATUS_DATAFORMAT;
|
||||||
|
|
||||||
unsigned int length = array_uint16_le (data);
|
unsigned int length = array_uint16_le (data);
|
||||||
if (length > size) {
|
if (length > size)
|
||||||
status = DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
goto error_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int extra = 0;
|
unsigned int extra = 0;
|
||||||
const unsigned char marker[3] = {0xAA, 0xBB, 0xCC};
|
const unsigned char marker[3] = {0xAA, 0xBB, 0xCC};
|
||||||
if (memcmp (data + length - 3, marker, sizeof (marker)) == 0) {
|
if (memcmp (data + length - 3, marker, sizeof (marker)) == 0) {
|
||||||
if (model == PUCKAIR)
|
if (parser->model == PUCKAIR)
|
||||||
extra = 7;
|
extra = 7;
|
||||||
else
|
else
|
||||||
extra = 12;
|
extra = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length < 2 + extra + 3) {
|
if (length < 2 + extra + 3)
|
||||||
status = DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
goto error_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int mode = data[length - extra - 1];
|
unsigned int mode = data[length - extra - 1];
|
||||||
|
|
||||||
unsigned int header_size = 53;
|
unsigned int header_size = 53;
|
||||||
unsigned int sample_size = 2;
|
unsigned int sample_size = 2;
|
||||||
if (extra) {
|
if (extra) {
|
||||||
if (model == PUCKAIR)
|
if (parser->model == PUCKAIR)
|
||||||
sample_size = 3;
|
sample_size = 3;
|
||||||
else
|
else
|
||||||
sample_size = 5;
|
sample_size = 5;
|
||||||
}
|
}
|
||||||
if (mode == freedive) {
|
if (mode == parser->freedive) {
|
||||||
header_size = 28;
|
header_size = 28;
|
||||||
sample_size = 6;
|
sample_size = 6;
|
||||||
}
|
}
|
||||||
@ -140,14 +169,12 @@ mares_nemo_parser_create (dc_parser_t **out, dc_context_t *context, const unsign
|
|||||||
unsigned int nsamples = array_uint16_le (data + length - extra - 3);
|
unsigned int nsamples = array_uint16_le (data + length - extra - 3);
|
||||||
|
|
||||||
unsigned int nbytes = 2 + nsamples * sample_size + header_size + extra;
|
unsigned int nbytes = 2 + nsamples * sample_size + header_size + extra;
|
||||||
if (length != nbytes) {
|
if (length != nbytes)
|
||||||
status = DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
goto error_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the default values.
|
// Store the new state.
|
||||||
parser->model = model;
|
parser->base.data = data;
|
||||||
parser->freedive = freedive;
|
parser->base.size = size;
|
||||||
parser->mode = mode;
|
parser->mode = mode;
|
||||||
parser->length = length;
|
parser->length = length;
|
||||||
parser->sample_count = nsamples;
|
parser->sample_count = nsamples;
|
||||||
@ -155,13 +182,7 @@ mares_nemo_parser_create (dc_parser_t **out, dc_context_t *context, const unsign
|
|||||||
parser->header = header_size;
|
parser->header = header_size;
|
||||||
parser->extra = extra;
|
parser->extra = extra;
|
||||||
|
|
||||||
*out = (dc_parser_t*) parser;
|
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
|
|
||||||
error_free:
|
|
||||||
dc_parser_deallocate ((dc_parser_t *) parser);
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -230,7 +251,6 @@ mares_nemo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign
|
|||||||
}
|
}
|
||||||
gasmix->helium = 0.0;
|
gasmix->helium = 0.0;
|
||||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_TANK_COUNT:
|
case DC_FIELD_TANK_COUNT:
|
||||||
if (parser->extra)
|
if (parser->extra)
|
||||||
@ -270,7 +290,6 @@ mares_nemo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign
|
|||||||
} else {
|
} else {
|
||||||
tank->gasmix = DC_GASMIX_UNKNOWN;
|
tank->gasmix = DC_GASMIX_UNKNOWN;
|
||||||
}
|
}
|
||||||
tank->usage = DC_USAGE_NONE;
|
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_TEMPERATURE_MINIMUM:
|
case DC_FIELD_TEMPERATURE_MINIMUM:
|
||||||
*((double *) value) = (signed char) p[53 - 11];
|
*((double *) value) = (signed char) p[53 - 11];
|
||||||
@ -363,17 +382,17 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
|||||||
|
|
||||||
// Time (seconds).
|
// Time (seconds).
|
||||||
time += 20;
|
time += 20;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Depth (1/10 m).
|
// Depth (1/10 m).
|
||||||
sample.depth = depth / 10.0;
|
sample.depth = depth / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
// Gas change.
|
// Gas change.
|
||||||
if (gasmix != gasmix_previous) {
|
if (gasmix != gasmix_previous) {
|
||||||
sample.gasmix = gasmix;
|
sample.gasmix = gasmix;
|
||||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
gasmix_previous = gasmix;
|
gasmix_previous = gasmix;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,7 +402,7 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
|||||||
sample.event.time = 0;
|
sample.event.time = 0;
|
||||||
sample.event.flags = 0;
|
sample.event.flags = 0;
|
||||||
sample.event.value = ascent;
|
sample.event.value = ascent;
|
||||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deco violation
|
// Deco violation
|
||||||
@ -392,7 +411,7 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
|||||||
sample.event.time = 0;
|
sample.event.time = 0;
|
||||||
sample.event.flags = 0;
|
sample.event.flags = 0;
|
||||||
sample.event.value = 0;
|
sample.event.value = 0;
|
||||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deco stop
|
// Deco stop
|
||||||
@ -403,21 +422,20 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
|||||||
}
|
}
|
||||||
sample.deco.time = 0;
|
sample.deco.time = 0;
|
||||||
sample.deco.depth = 0.0;
|
sample.deco.depth = 0.0;
|
||||||
sample.deco.tts = 0;
|
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
|
||||||
|
|
||||||
// Pressure (1 bar).
|
// Pressure (1 bar).
|
||||||
if (parser->sample_size == 3) {
|
if (parser->sample_size == 3) {
|
||||||
sample.pressure.tank = 0;
|
sample.pressure.tank = 0;
|
||||||
sample.pressure.value = data[idx + 2];
|
sample.pressure.value = data[idx + 2];
|
||||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||||
} else if (parser->sample_size == 5) {
|
} else if (parser->sample_size == 5) {
|
||||||
unsigned int type = (time / 20) % 3;
|
unsigned int type = (time / 20) % 3;
|
||||||
if (type == 0) {
|
if (type == 0) {
|
||||||
pressure -= data[idx + 2] * 100;
|
pressure -= data[idx + 2] * 100;
|
||||||
sample.pressure.tank = 0;
|
sample.pressure.tank = 0;
|
||||||
sample.pressure.value = pressure / 100.0;
|
sample.pressure.value = pressure / 100.0;
|
||||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -441,12 +459,12 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
|||||||
|
|
||||||
// Surface Time (seconds).
|
// Surface Time (seconds).
|
||||||
time += surftime;
|
time += surftime;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Surface Depth (0 m).
|
// Surface Depth (0 m).
|
||||||
sample.depth = 0.0;
|
sample.depth = 0.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
if (profiles) {
|
if (profiles) {
|
||||||
// Get the freedive sample interval for this model.
|
// Get the freedive sample interval for this model.
|
||||||
@ -482,12 +500,12 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
|||||||
time += interval;
|
time += interval;
|
||||||
if (time > maxtime)
|
if (time > maxtime)
|
||||||
time = maxtime; // Adjust the last sample.
|
time = maxtime; // Adjust the last sample.
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Depth (1/10 m).
|
// Depth (1/10 m).
|
||||||
sample.depth = depth / 10.0;
|
sample.depth = depth / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the number of samples in the profile data
|
// Verify that the number of samples in the profile data
|
||||||
@ -501,12 +519,12 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
|||||||
} else {
|
} else {
|
||||||
// Dive Time (seconds).
|
// Dive Time (seconds).
|
||||||
time += divetime;
|
time += divetime;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Maximum Depth (1/10 m).
|
// Maximum Depth (1/10 m).
|
||||||
sample.depth = maxdepth / 10.0;
|
sample.depth = maxdepth / 10.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,7 +35,7 @@ dc_status_t
|
|||||||
mclean_extreme_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
mclean_extreme_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
mclean_extreme_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
mclean_extreme_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,6 +58,7 @@ struct mclean_extreme_parser_t {
|
|||||||
unsigned int gasmix[NGASMIXES];
|
unsigned int gasmix[NGASMIXES];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static dc_status_t mclean_extreme_parser_set_data(dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t mclean_extreme_parser_get_datetime(dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t mclean_extreme_parser_get_datetime(dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t mclean_extreme_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t mclean_extreme_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t mclean_extreme_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t mclean_extreme_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -65,6 +66,7 @@ static dc_status_t mclean_extreme_parser_samples_foreach(dc_parser_t *abstract,
|
|||||||
static const dc_parser_vtable_t mclean_extreme_parser_vtable = {
|
static const dc_parser_vtable_t mclean_extreme_parser_vtable = {
|
||||||
sizeof(mclean_extreme_parser_t),
|
sizeof(mclean_extreme_parser_t),
|
||||||
DC_FAMILY_MCLEAN_EXTREME,
|
DC_FAMILY_MCLEAN_EXTREME,
|
||||||
|
mclean_extreme_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -75,7 +77,7 @@ static const dc_parser_vtable_t mclean_extreme_parser_vtable = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
mclean_extreme_parser_create(dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
mclean_extreme_parser_create(dc_parser_t **out, dc_context_t *context)
|
||||||
{
|
{
|
||||||
mclean_extreme_parser_t *parser = NULL;
|
mclean_extreme_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -84,7 +86,7 @@ mclean_extreme_parser_create(dc_parser_t **out, dc_context_t *context, const uns
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (mclean_extreme_parser_t *)dc_parser_allocate(context, &mclean_extreme_parser_vtable, data, size);
|
parser = (mclean_extreme_parser_t *)dc_parser_allocate(context, &mclean_extreme_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR(context, "Failed to allocate memory.");
|
ERROR(context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -102,6 +104,21 @@ mclean_extreme_parser_create(dc_parser_t **out, dc_context_t *context, const uns
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
mclean_extreme_parser_set_data(dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
mclean_extreme_parser_t *parser = (mclean_extreme_parser_t *)abstract;
|
||||||
|
|
||||||
|
// Reset the cache.
|
||||||
|
parser->cached = 0;
|
||||||
|
parser->ngasmixes = 0;
|
||||||
|
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||||
|
parser->gasmix[i] = INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
mclean_extreme_parser_get_datetime(dc_parser_t *abstract, dc_datetime_t *datetime)
|
mclean_extreme_parser_get_datetime(dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -204,7 +221,6 @@ mclean_extreme_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, uns
|
|||||||
*((unsigned int *)value) = parser->ngasmixes;
|
*((unsigned int *)value) = parser->ngasmixes;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
gasmix->helium = 0.01 * abstract->data[0x0001 + 1 + 2 * parser->gasmix[flags]];
|
gasmix->helium = 0.01 * abstract->data[0x0001 + 1 + 2 * parser->gasmix[flags]];
|
||||||
gasmix->oxygen = 0.01 * abstract->data[0x0001 + 0 + 2 * parser->gasmix[flags]];
|
gasmix->oxygen = 0.01 * abstract->data[0x0001 + 0 + 2 * parser->gasmix[flags]];
|
||||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||||
@ -253,14 +269,14 @@ mclean_extreme_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback_
|
|||||||
const unsigned int setpoint = abstract->data[0x0013 + sp_index];
|
const unsigned int setpoint = abstract->data[0x0013 + sp_index];
|
||||||
|
|
||||||
time += interval;
|
time += interval;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback(DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
sample.depth = 0.1 * depth;
|
sample.depth = 0.1 * depth;
|
||||||
if (callback) callback(DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
sample.temperature = temperature;
|
sample.temperature = temperature;
|
||||||
if (callback) callback(DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
|
|
||||||
if (gasmix_id != gasmix_previous) {
|
if (gasmix_id != gasmix_previous) {
|
||||||
// Find the gasmix in the list.
|
// Find the gasmix in the list.
|
||||||
@ -282,13 +298,13 @@ mclean_extreme_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback_
|
|||||||
}
|
}
|
||||||
|
|
||||||
sample.gasmix = idx;
|
sample.gasmix = idx;
|
||||||
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
gasmix_previous = gasmix_id;
|
gasmix_previous = gasmix_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ccr) {
|
if (ccr) {
|
||||||
sample.setpoint = 0.01 * setpoint;
|
sample.setpoint = 0.01 * setpoint;
|
||||||
if (callback) callback(DC_SAMPLE_SETPOINT, &sample, userdata);
|
if (callback) callback(DC_SAMPLE_SETPOINT, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += SZ_SAMPLE;
|
offset += SZ_SAMPLE;
|
||||||
|
|||||||
@ -86,8 +86,6 @@ static const oceanic_common_device_vtable_t oceanic_atom2_device_vtable = {
|
|||||||
NULL, /* timesync */
|
NULL, /* timesync */
|
||||||
oceanic_atom2_device_close /* close */
|
oceanic_atom2_device_close /* close */
|
||||||
},
|
},
|
||||||
oceanic_common_device_devinfo,
|
|
||||||
oceanic_common_device_pointers,
|
|
||||||
oceanic_common_device_logbook,
|
oceanic_common_device_logbook,
|
||||||
oceanic_common_device_profile,
|
oceanic_common_device_profile,
|
||||||
};
|
};
|
||||||
@ -100,11 +98,10 @@ static const oceanic_common_layout_t aeris_f10_layout = {
|
|||||||
0x0100, /* rb_logbook_begin */
|
0x0100, /* rb_logbook_begin */
|
||||||
0x0D80, /* rb_logbook_end */
|
0x0D80, /* rb_logbook_end */
|
||||||
32, /* rb_logbook_entry_size */
|
32, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x0D80, /* rb_profile_begin */
|
0x0D80, /* rb_profile_begin */
|
||||||
0x10000, /* rb_profile_end */
|
0x10000, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
3, /* pt_mode_logbook */
|
2, /* pt_mode_logbook */
|
||||||
0, /* pt_mode_serial */
|
0, /* pt_mode_serial */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -116,11 +113,10 @@ static const oceanic_common_layout_t aeris_f11_layout = {
|
|||||||
0x0100, /* rb_logbook_begin */
|
0x0100, /* rb_logbook_begin */
|
||||||
0x0D80, /* rb_logbook_end */
|
0x0D80, /* rb_logbook_end */
|
||||||
32, /* rb_logbook_entry_size */
|
32, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x0D80, /* rb_profile_begin */
|
0x0D80, /* rb_profile_begin */
|
||||||
0x20000, /* rb_profile_end */
|
0x20000, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
2, /* pt_mode_logbook */
|
3, /* pt_mode_logbook */
|
||||||
0, /* pt_mode_serial */
|
0, /* pt_mode_serial */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -132,7 +128,6 @@ static const oceanic_common_layout_t oceanic_default_layout = {
|
|||||||
0x0240, /* rb_logbook_begin */
|
0x0240, /* rb_logbook_begin */
|
||||||
0x0A40, /* rb_logbook_end */
|
0x0A40, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x0A40, /* rb_profile_begin */
|
0x0A40, /* rb_profile_begin */
|
||||||
0x10000, /* rb_profile_end */
|
0x10000, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -148,7 +143,6 @@ static const oceanic_common_layout_t oceanic_atom1_layout = {
|
|||||||
0x0240, /* rb_logbook_begin */
|
0x0240, /* rb_logbook_begin */
|
||||||
0x0440, /* rb_logbook_end */
|
0x0440, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x0440, /* rb_profile_begin */
|
0x0440, /* rb_profile_begin */
|
||||||
0x8000, /* rb_profile_end */
|
0x8000, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -164,7 +158,6 @@ static const oceanic_common_layout_t oceanic_atom2a_layout = {
|
|||||||
0x0240, /* rb_logbook_begin */
|
0x0240, /* rb_logbook_begin */
|
||||||
0x0A40, /* rb_logbook_end */
|
0x0A40, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x0A40, /* rb_profile_begin */
|
0x0A40, /* rb_profile_begin */
|
||||||
0xFE00, /* rb_profile_end */
|
0xFE00, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -180,7 +173,6 @@ static const oceanic_common_layout_t oceanic_atom2b_layout = {
|
|||||||
0x0240, /* rb_logbook_begin */
|
0x0240, /* rb_logbook_begin */
|
||||||
0x0A40, /* rb_logbook_end */
|
0x0A40, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x0A40, /* rb_profile_begin */
|
0x0A40, /* rb_profile_begin */
|
||||||
0xFE00, /* rb_profile_end */
|
0xFE00, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -196,7 +188,6 @@ static const oceanic_common_layout_t oceanic_atom2c_layout = {
|
|||||||
0x0240, /* rb_logbook_begin */
|
0x0240, /* rb_logbook_begin */
|
||||||
0x0A40, /* rb_logbook_end */
|
0x0A40, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x0A40, /* rb_profile_begin */
|
0x0A40, /* rb_profile_begin */
|
||||||
0xFFF0, /* rb_profile_end */
|
0xFFF0, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -212,7 +203,6 @@ static const oceanic_common_layout_t sherwood_wisdom_layout = {
|
|||||||
0x03D0, /* rb_logbook_begin */
|
0x03D0, /* rb_logbook_begin */
|
||||||
0x0A40, /* rb_logbook_end */
|
0x0A40, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x0A40, /* rb_profile_begin */
|
0x0A40, /* rb_profile_begin */
|
||||||
0xFE00, /* rb_profile_end */
|
0xFE00, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -228,7 +218,6 @@ static const oceanic_common_layout_t oceanic_proplus3_layout = {
|
|||||||
0x03E0, /* rb_logbook_begin */
|
0x03E0, /* rb_logbook_begin */
|
||||||
0x0A40, /* rb_logbook_end */
|
0x0A40, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x0A40, /* rb_profile_begin */
|
0x0A40, /* rb_profile_begin */
|
||||||
0xFE00, /* rb_profile_end */
|
0xFE00, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -244,7 +233,6 @@ static const oceanic_common_layout_t tusa_zenair_layout = {
|
|||||||
0x0240, /* rb_logbook_begin */
|
0x0240, /* rb_logbook_begin */
|
||||||
0x0A40, /* rb_logbook_end */
|
0x0A40, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x0A40, /* rb_profile_begin */
|
0x0A40, /* rb_profile_begin */
|
||||||
0xFE00, /* rb_profile_end */
|
0xFE00, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -260,7 +248,6 @@ static const oceanic_common_layout_t oceanic_oc1_layout = {
|
|||||||
0x0240, /* rb_logbook_begin */
|
0x0240, /* rb_logbook_begin */
|
||||||
0x0A40, /* rb_logbook_end */
|
0x0A40, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x0A40, /* rb_profile_begin */
|
0x0A40, /* rb_profile_begin */
|
||||||
0x1FE00, /* rb_profile_end */
|
0x1FE00, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -276,7 +263,6 @@ static const oceanic_common_layout_t oceanic_oci_layout = {
|
|||||||
0x10C0, /* rb_logbook_begin */
|
0x10C0, /* rb_logbook_begin */
|
||||||
0x1400, /* rb_logbook_end */
|
0x1400, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x1400, /* rb_profile_begin */
|
0x1400, /* rb_profile_begin */
|
||||||
0x1FE00, /* rb_profile_end */
|
0x1FE00, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -292,7 +278,6 @@ static const oceanic_common_layout_t oceanic_atom3_layout = {
|
|||||||
0x0400, /* rb_logbook_begin */
|
0x0400, /* rb_logbook_begin */
|
||||||
0x0A40, /* rb_logbook_end */
|
0x0A40, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x0A40, /* rb_profile_begin */
|
0x0A40, /* rb_profile_begin */
|
||||||
0x1FE00, /* rb_profile_end */
|
0x1FE00, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -308,7 +293,6 @@ static const oceanic_common_layout_t oceanic_vt4_layout = {
|
|||||||
0x0420, /* rb_logbook_begin */
|
0x0420, /* rb_logbook_begin */
|
||||||
0x0A40, /* rb_logbook_end */
|
0x0A40, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x0A40, /* rb_profile_begin */
|
0x0A40, /* rb_profile_begin */
|
||||||
0x1FE00, /* rb_profile_end */
|
0x1FE00, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -324,7 +308,6 @@ static const oceanic_common_layout_t hollis_tx1_layout = {
|
|||||||
0x0780, /* rb_logbook_begin */
|
0x0780, /* rb_logbook_begin */
|
||||||
0x1000, /* rb_logbook_end */
|
0x1000, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x1000, /* rb_profile_begin */
|
0x1000, /* rb_profile_begin */
|
||||||
0x40000, /* rb_profile_end */
|
0x40000, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -340,7 +323,6 @@ static const oceanic_common_layout_t oceanic_veo1_layout = {
|
|||||||
0x0400, /* rb_logbook_begin */
|
0x0400, /* rb_logbook_begin */
|
||||||
0x0400, /* rb_logbook_end */
|
0x0400, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x0400, /* rb_profile_begin */
|
0x0400, /* rb_profile_begin */
|
||||||
0x0400, /* rb_profile_end */
|
0x0400, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -356,9 +338,8 @@ static const oceanic_common_layout_t oceanic_reactpro_layout = {
|
|||||||
0x0400, /* rb_logbook_begin */
|
0x0400, /* rb_logbook_begin */
|
||||||
0x0600, /* rb_logbook_end */
|
0x0600, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x0600, /* rb_profile_begin */
|
0x0600, /* rb_profile_begin */
|
||||||
0xFE00, /* rb_profile_end */
|
0xFFF0, /* rb_profile_end */
|
||||||
1, /* pt_mode_global */
|
1, /* pt_mode_global */
|
||||||
1, /* pt_mode_logbook */
|
1, /* pt_mode_logbook */
|
||||||
0, /* pt_mode_serial */
|
0, /* pt_mode_serial */
|
||||||
@ -372,7 +353,6 @@ static const oceanic_common_layout_t oceanic_proplusx_layout = {
|
|||||||
0x1000, /* rb_logbook_begin */
|
0x1000, /* rb_logbook_begin */
|
||||||
0x10000, /* rb_logbook_end */
|
0x10000, /* rb_logbook_end */
|
||||||
16, /* rb_logbook_entry_size */
|
16, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x40000, /* rb_profile_begin */
|
0x40000, /* rb_profile_begin */
|
||||||
0x440000, /* rb_profile_end */
|
0x440000, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -388,7 +368,6 @@ static const oceanic_common_layout_t aqualung_i770r_layout = {
|
|||||||
0x2000, /* rb_logbook_begin */
|
0x2000, /* rb_logbook_begin */
|
||||||
0x10000, /* rb_logbook_end */
|
0x10000, /* rb_logbook_end */
|
||||||
16, /* rb_logbook_entry_size */
|
16, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x40000, /* rb_profile_begin */
|
0x40000, /* rb_profile_begin */
|
||||||
0x640000, /* rb_profile_end */
|
0x640000, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -404,7 +383,6 @@ static const oceanic_common_layout_t aeris_a300cs_layout = {
|
|||||||
0x0900, /* rb_logbook_begin */
|
0x0900, /* rb_logbook_begin */
|
||||||
0x1000, /* rb_logbook_end */
|
0x1000, /* rb_logbook_end */
|
||||||
16, /* rb_logbook_entry_size */
|
16, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x1000, /* rb_profile_begin */
|
0x1000, /* rb_profile_begin */
|
||||||
0x3FE00, /* rb_profile_end */
|
0x3FE00, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -420,7 +398,6 @@ static const oceanic_common_layout_t aqualung_i450t_layout = {
|
|||||||
0x10C0, /* rb_logbook_begin */
|
0x10C0, /* rb_logbook_begin */
|
||||||
0x1400, /* rb_logbook_end */
|
0x1400, /* rb_logbook_end */
|
||||||
16, /* rb_logbook_entry_size */
|
16, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x1400, /* rb_profile_begin */
|
0x1400, /* rb_profile_begin */
|
||||||
0x3FE00, /* rb_profile_end */
|
0x3FE00, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -438,14 +415,13 @@ static const oceanic_common_version_t versions[] = {
|
|||||||
{"MANTA R\0\0 512K", 0, MANTA, &oceanic_atom2c_layout},
|
{"MANTA R\0\0 512K", 0, MANTA, &oceanic_atom2c_layout},
|
||||||
{"2M ATOM r\0\0 512K", 0x3349, ATOM2, &oceanic_atom2a_layout},
|
{"2M ATOM r\0\0 512K", 0x3349, ATOM2, &oceanic_atom2a_layout},
|
||||||
{"2M ATOM r\0\0 512K", 0, ATOM2, &oceanic_atom2c_layout},
|
{"2M ATOM r\0\0 512K", 0, ATOM2, &oceanic_atom2c_layout},
|
||||||
{"OCE GEO R\0\0 512K", 0x3242, GEO, &oceanic_atom2a_layout},
|
|
||||||
{"OCE GEO R\0\0 512K", 0, GEO, &oceanic_atom2c_layout},
|
|
||||||
|
|
||||||
{"INSIGHT2 \0\0 512K", 0, INSIGHT2, &oceanic_atom2a_layout},
|
{"INSIGHT2 \0\0 512K", 0, INSIGHT2, &oceanic_atom2a_layout},
|
||||||
{"OCEVEO30 \0\0 512K", 0, VEO30, &oceanic_atom2a_layout},
|
{"OCEVEO30 \0\0 512K", 0, VEO30, &oceanic_atom2a_layout},
|
||||||
{"ATMOSAI R\0\0 512K", 0, ATMOSAI2, &oceanic_atom2a_layout},
|
{"ATMOSAI R\0\0 512K", 0, ATMOSAI2, &oceanic_atom2a_layout},
|
||||||
{"PROPLUS2 \0\0 512K", 0, PROPLUS21, &oceanic_atom2a_layout},
|
{"PROPLUS2 \0\0 512K", 0, PROPLUS21, &oceanic_atom2a_layout},
|
||||||
{"OCEGEO20 \0\0 512K", 0, GEO20, &oceanic_atom2a_layout},
|
{"OCEGEO20 \0\0 512K", 0, GEO20, &oceanic_atom2a_layout},
|
||||||
|
{"OCE GEO R\0\0 512K", 0, GEO, &oceanic_atom2a_layout},
|
||||||
{"AQUAI200 \0\0 512K", 0, I200, &oceanic_atom2a_layout},
|
{"AQUAI200 \0\0 512K", 0, I200, &oceanic_atom2a_layout},
|
||||||
{"AQUA200C \0\0 512K", 0, I200C, &oceanic_atom2a_layout},
|
{"AQUA200C \0\0 512K", 0, I200C, &oceanic_atom2a_layout},
|
||||||
|
|
||||||
|
|||||||
@ -37,7 +37,7 @@ dc_status_t
|
|||||||
oceanic_atom2_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
oceanic_atom2_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
oceanic_atom2_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
oceanic_atom2_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,12 +35,6 @@
|
|||||||
#define GAUGE 1
|
#define GAUGE 1
|
||||||
#define FREEDIVE 2
|
#define FREEDIVE 2
|
||||||
|
|
||||||
#define DSX_CC 0
|
|
||||||
#define DSX_OC 1
|
|
||||||
#define DSX_SIDEMOUNT 2
|
|
||||||
#define DSX_SIDEGAUGE 3
|
|
||||||
#define DSX_GAUGE 4
|
|
||||||
|
|
||||||
#define NGASMIXES 6
|
#define NGASMIXES 6
|
||||||
|
|
||||||
#define HEADER 1
|
#define HEADER 1
|
||||||
@ -51,7 +45,6 @@ typedef struct oceanic_atom2_parser_t oceanic_atom2_parser_t;
|
|||||||
struct oceanic_atom2_parser_t {
|
struct oceanic_atom2_parser_t {
|
||||||
dc_parser_t base;
|
dc_parser_t base;
|
||||||
unsigned int model;
|
unsigned int model;
|
||||||
unsigned int logbooksize;
|
|
||||||
unsigned int headersize;
|
unsigned int headersize;
|
||||||
unsigned int footersize;
|
unsigned int footersize;
|
||||||
// Cached fields.
|
// Cached fields.
|
||||||
@ -66,6 +59,7 @@ struct oceanic_atom2_parser_t {
|
|||||||
double maxdepth;
|
double maxdepth;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static dc_status_t oceanic_atom2_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -73,6 +67,7 @@ static dc_status_t oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract,
|
|||||||
static const dc_parser_vtable_t oceanic_atom2_parser_vtable = {
|
static const dc_parser_vtable_t oceanic_atom2_parser_vtable = {
|
||||||
sizeof(oceanic_atom2_parser_t),
|
sizeof(oceanic_atom2_parser_t),
|
||||||
DC_FAMILY_OCEANIC_ATOM2,
|
DC_FAMILY_OCEANIC_ATOM2,
|
||||||
|
oceanic_atom2_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -84,7 +79,7 @@ static const dc_parser_vtable_t oceanic_atom2_parser_vtable = {
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||||
{
|
{
|
||||||
oceanic_atom2_parser_t *parser = NULL;
|
oceanic_atom2_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -92,7 +87,7 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, const uns
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (oceanic_atom2_parser_t *) dc_parser_allocate (context, &oceanic_atom2_parser_vtable, data, size);
|
parser = (oceanic_atom2_parser_t *) dc_parser_allocate (context, &oceanic_atom2_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -100,7 +95,6 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, const uns
|
|||||||
|
|
||||||
// Set the default values.
|
// Set the default values.
|
||||||
parser->model = model;
|
parser->model = model;
|
||||||
parser->logbooksize = 0;
|
|
||||||
parser->headersize = 9 * PAGESIZE / 2;
|
parser->headersize = 9 * PAGESIZE / 2;
|
||||||
parser->footersize = 2 * PAGESIZE / 2;
|
parser->footersize = 2 * PAGESIZE / 2;
|
||||||
if (model == DATAMASK || model == COMPUMASK ||
|
if (model == DATAMASK || model == COMPUMASK ||
|
||||||
@ -139,14 +133,6 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, const uns
|
|||||||
} else if (model == I550C || model == WISDOM4 ||
|
} else if (model == I550C || model == WISDOM4 ||
|
||||||
model == I200CV2) {
|
model == I200CV2) {
|
||||||
parser->headersize = 5 * PAGESIZE / 2;
|
parser->headersize = 5 * PAGESIZE / 2;
|
||||||
} else if (model == I330R) {
|
|
||||||
parser->logbooksize = 64;
|
|
||||||
parser->headersize = parser->logbooksize + 80;
|
|
||||||
parser->footersize = 48;
|
|
||||||
} else if (model == DSX) {
|
|
||||||
parser->logbooksize = 512;
|
|
||||||
parser->headersize = parser->logbooksize + 256;
|
|
||||||
parser->footersize = 64;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parser->cached = 0;
|
parser->cached = 0;
|
||||||
@ -167,6 +153,28 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, const uns
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
oceanic_atom2_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
oceanic_atom2_parser_t *parser = (oceanic_atom2_parser_t *) abstract;
|
||||||
|
|
||||||
|
// Reset the cache.
|
||||||
|
parser->cached = 0;
|
||||||
|
parser->header = 0;
|
||||||
|
parser->footer = 0;
|
||||||
|
parser->mode = NORMAL;
|
||||||
|
parser->ngasmixes = 0;
|
||||||
|
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||||
|
parser->oxygen[i] = 0;
|
||||||
|
parser->helium[i] = 0;
|
||||||
|
}
|
||||||
|
parser->divetime = 0;
|
||||||
|
parser->maxdepth = 0.0;
|
||||||
|
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -186,18 +194,8 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim
|
|||||||
if (datetime) {
|
if (datetime) {
|
||||||
// AM/PM bit of the 12-hour clock.
|
// AM/PM bit of the 12-hour clock.
|
||||||
unsigned int pm = p[1] & 0x80;
|
unsigned int pm = p[1] & 0x80;
|
||||||
unsigned int have_ampm = 1;
|
|
||||||
|
|
||||||
switch (parser->model) {
|
switch (parser->model) {
|
||||||
case I330R:
|
|
||||||
case DSX:
|
|
||||||
datetime->year = p[7] + 2000;
|
|
||||||
datetime->month = p[6];
|
|
||||||
datetime->day = p[5];
|
|
||||||
datetime->hour = p[3];
|
|
||||||
datetime->minute = p[4];
|
|
||||||
have_ampm = 0;
|
|
||||||
break;
|
|
||||||
case OC1A:
|
case OC1A:
|
||||||
case OC1B:
|
case OC1B:
|
||||||
case OC1C:
|
case OC1C:
|
||||||
@ -306,11 +304,9 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim
|
|||||||
datetime->timezone = DC_TIMEZONE_NONE;
|
datetime->timezone = DC_TIMEZONE_NONE;
|
||||||
|
|
||||||
// Convert to a 24-hour clock.
|
// Convert to a 24-hour clock.
|
||||||
if (have_ampm) {
|
datetime->hour %= 12;
|
||||||
datetime->hour %= 12;
|
if (pm)
|
||||||
if (pm)
|
datetime->hour += 12;
|
||||||
datetime->hour += 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Workaround for the year 2010 problem.
|
* Workaround for the year 2010 problem.
|
||||||
@ -385,10 +381,6 @@ oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser)
|
|||||||
} else if (parser->model == VEO20 || parser->model == VEO30 ||
|
} else if (parser->model == VEO20 || parser->model == VEO30 ||
|
||||||
parser->model == OCS) {
|
parser->model == OCS) {
|
||||||
mode = (data[1] & 0x60) >> 5;
|
mode = (data[1] & 0x60) >> 5;
|
||||||
} else if (parser->model == I330R) {
|
|
||||||
mode = data[2];
|
|
||||||
} else if (parser->model == DSX) {
|
|
||||||
mode = data[45];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the gas mixes.
|
// Get the gas mixes.
|
||||||
@ -446,17 +438,6 @@ oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser)
|
|||||||
} else if (parser->model == WISDOM4) {
|
} else if (parser->model == WISDOM4) {
|
||||||
o2_offset = header + 4;
|
o2_offset = header + 4;
|
||||||
ngasmixes = 1;
|
ngasmixes = 1;
|
||||||
} else if (parser->model == I330R) {
|
|
||||||
ngasmixes = 3;
|
|
||||||
o2_offset = parser->logbooksize + 16;
|
|
||||||
} else if (parser->model == DSX) {
|
|
||||||
if (mode < DSX_SIDEGAUGE) {
|
|
||||||
o2_offset = parser->logbooksize + 0x89 + mode * 16;
|
|
||||||
he_offset = parser->logbooksize + 0xB9 + mode * 16;
|
|
||||||
ngasmixes = 6;
|
|
||||||
} else {
|
|
||||||
ngasmixes = 0;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
o2_offset = header + 4;
|
o2_offset = header + 4;
|
||||||
ngasmixes = 3;
|
ngasmixes = 3;
|
||||||
@ -470,10 +451,6 @@ oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser)
|
|||||||
for (unsigned int i = 0; i < ngasmixes; ++i) {
|
for (unsigned int i = 0; i < ngasmixes; ++i) {
|
||||||
if (data[o2_offset + i * o2_step]) {
|
if (data[o2_offset + i * o2_step]) {
|
||||||
parser->oxygen[i] = data[o2_offset + i * o2_step];
|
parser->oxygen[i] = data[o2_offset + i * o2_step];
|
||||||
// The i330R uses 20 as "Air" and 21 as 21% Nitrox
|
|
||||||
if (parser->model == I330R && parser->oxygen[i] == 20) {
|
|
||||||
parser->oxygen[i] = 21;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
parser->oxygen[i] = 21;
|
parser->oxygen[i] = 21;
|
||||||
}
|
}
|
||||||
@ -532,23 +509,13 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns
|
|||||||
parser->model == F11A || parser->model == F11B ||
|
parser->model == F11A || parser->model == F11B ||
|
||||||
parser->model == MUNDIAL2 || parser->model == MUNDIAL3)
|
parser->model == MUNDIAL2 || parser->model == MUNDIAL3)
|
||||||
*((double *) value) = array_uint16_le (data + 4) / 16.0 * FEET;
|
*((double *) value) = array_uint16_le (data + 4) / 16.0 * FEET;
|
||||||
else if (parser->model == I330R || parser->model == DSX)
|
|
||||||
*((double *) value) = array_uint16_le (data + parser->footer + 10) / 10.0 * FEET;
|
|
||||||
else
|
else
|
||||||
*((double *) value) = (array_uint16_le (data + parser->footer + 4) & 0x0FFF) / 16.0 * FEET;
|
*((double *) value) = (array_uint16_le (data + parser->footer + 4) & 0x0FFF) / 16.0 * FEET;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_AVGDEPTH:
|
|
||||||
if (parser->model == I330R || parser->model == DSX) {
|
|
||||||
*((double *) value) = array_uint16_le (data + parser->footer + 12) / 10.0 * FEET;
|
|
||||||
} else {
|
|
||||||
return DC_STATUS_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DC_FIELD_GASMIX_COUNT:
|
case DC_FIELD_GASMIX_COUNT:
|
||||||
*((unsigned int *) value) = parser->ngasmixes;
|
*((unsigned int *) value) = parser->ngasmixes;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
gasmix->oxygen = parser->oxygen[flags] / 100.0;
|
gasmix->oxygen = parser->oxygen[flags] / 100.0;
|
||||||
gasmix->helium = parser->helium[flags] / 100.0;
|
gasmix->helium = parser->helium[flags] / 100.0;
|
||||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||||
@ -562,49 +529,23 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns
|
|||||||
water->type = DC_WATER_SALT;
|
water->type = DC_WATER_SALT;
|
||||||
}
|
}
|
||||||
water->density = 0.0;
|
water->density = 0.0;
|
||||||
} else if (parser->model == I330R || parser->model == DSX) {
|
|
||||||
unsigned int settings = array_uint32_le (data + parser->logbooksize + 12);
|
|
||||||
if (settings & 0x10000) {
|
|
||||||
water->type = DC_WATER_FRESH;
|
|
||||||
} else {
|
|
||||||
water->type = DC_WATER_SALT;
|
|
||||||
}
|
|
||||||
water->density = 0.0;
|
|
||||||
} else {
|
} else {
|
||||||
return DC_STATUS_UNSUPPORTED;
|
return DC_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_DIVEMODE:
|
case DC_FIELD_DIVEMODE:
|
||||||
if (parser->model == DSX) {
|
switch (parser->mode) {
|
||||||
switch (parser->mode) {
|
case NORMAL:
|
||||||
case DSX_OC:
|
*((unsigned int *) value) = DC_DIVEMODE_OC;
|
||||||
case DSX_SIDEMOUNT:
|
break;
|
||||||
*((unsigned int *) value) = DC_DIVEMODE_OC;
|
case GAUGE:
|
||||||
break;
|
*((unsigned int *) value) = DC_DIVEMODE_GAUGE;
|
||||||
case DSX_SIDEGAUGE:
|
break;
|
||||||
case DSX_GAUGE:
|
case FREEDIVE:
|
||||||
*((unsigned int *) value) = DC_DIVEMODE_GAUGE;
|
*((unsigned int *) value) = DC_DIVEMODE_FREEDIVE;
|
||||||
break;
|
break;
|
||||||
case DSX_CC:
|
default:
|
||||||
*((unsigned int *) value) = DC_DIVEMODE_CCR;
|
return DC_STATUS_DATAFORMAT;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (parser->mode) {
|
|
||||||
case NORMAL:
|
|
||||||
*((unsigned int *) value) = DC_DIVEMODE_OC;
|
|
||||||
break;
|
|
||||||
case GAUGE:
|
|
||||||
*((unsigned int *) value) = DC_DIVEMODE_GAUGE;
|
|
||||||
break;
|
|
||||||
case FREEDIVE:
|
|
||||||
*((unsigned int *) value) = DC_DIVEMODE_FREEDIVE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -645,7 +586,7 @@ oceanic_atom2_parser_vendor (oceanic_atom2_parser_t *parser, const unsigned char
|
|||||||
sample.vendor.type = SAMPLE_VENDOR_OCEANIC_ATOM2;
|
sample.vendor.type = SAMPLE_VENDOR_OCEANIC_ATOM2;
|
||||||
sample.vendor.size = length;
|
sample.vendor.size = length;
|
||||||
sample.vendor.data = data + offset;
|
sample.vendor.data = data + offset;
|
||||||
if (callback) callback (DC_SAMPLE_VENDOR, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_VENDOR, sample, userdata);
|
||||||
|
|
||||||
offset += length;
|
offset += length;
|
||||||
}
|
}
|
||||||
@ -667,25 +608,30 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
|
|
||||||
unsigned int extratime = 0;
|
unsigned int extratime = 0;
|
||||||
unsigned int time = 0;
|
unsigned int time = 0;
|
||||||
unsigned int interval = 1000;
|
unsigned int interval = 1;
|
||||||
|
unsigned int samplerate = 1;
|
||||||
if (parser->mode != FREEDIVE) {
|
if (parser->mode != FREEDIVE) {
|
||||||
if (parser->model == I330R || parser->model == DSX) {
|
unsigned int offset = 0x17;
|
||||||
interval = data[parser->logbooksize + 36] * 1000;
|
if (parser->model == A300CS || parser->model == VTX ||
|
||||||
} else {
|
parser->model == I450T || parser->model == I750TC ||
|
||||||
unsigned int offset = 0x17;
|
parser->model == PROPLUSX || parser->model == I770R ||
|
||||||
if (parser->model == A300CS || parser->model == VTX ||
|
parser->model == SAGE || parser->model == BEACON)
|
||||||
parser->model == I450T || parser->model == I750TC ||
|
offset = 0x1f;
|
||||||
parser->model == PROPLUSX || parser->model == I770R ||
|
const unsigned int intervals[] = {2, 15, 30, 60};
|
||||||
parser->model == SAGE || parser->model == BEACON)
|
unsigned int idx = data[offset] & 0x03;
|
||||||
offset = 0x1f;
|
interval = intervals[idx];
|
||||||
const unsigned int intervals[] = {2000, 15000, 30000, 60000};
|
|
||||||
unsigned int idx = data[offset] & 0x03;
|
|
||||||
interval = intervals[idx];
|
|
||||||
}
|
|
||||||
} else if (parser->model == F11A || parser->model == F11B) {
|
} else if (parser->model == F11A || parser->model == F11B) {
|
||||||
const unsigned int intervals[] = {250, 500, 1000, 2000};
|
const unsigned int intervals[] = {1, 1, 1, 2};
|
||||||
|
const unsigned int samplerates[] = {4, 2, 1, 1};
|
||||||
unsigned int idx = data[0x29] & 0x03;
|
unsigned int idx = data[0x29] & 0x03;
|
||||||
interval = intervals[idx];
|
interval = intervals[idx];
|
||||||
|
samplerate = samplerates[idx];
|
||||||
|
if (samplerate > 1) {
|
||||||
|
// Some models supports multiple samples per second.
|
||||||
|
// Since our smallest unit of time is one second, we can't
|
||||||
|
// represent this, and the extra samples will get dropped.
|
||||||
|
WARNING(abstract->context, "Multiple samples per second are not supported!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int samplesize = PAGESIZE / 2;
|
unsigned int samplesize = PAGESIZE / 2;
|
||||||
@ -704,10 +650,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
parser->model == I750TC || parser->model == PROPLUSX ||
|
parser->model == I750TC || parser->model == PROPLUSX ||
|
||||||
parser->model == I770R || parser->model == I470TC ||
|
parser->model == I770R || parser->model == I470TC ||
|
||||||
parser->model == SAGE || parser->model == BEACON ||
|
parser->model == SAGE || parser->model == BEACON ||
|
||||||
parser->model == GEOAIR || parser->model == I330R) {
|
parser->model == GEOAIR) {
|
||||||
samplesize = PAGESIZE;
|
samplesize = PAGESIZE;
|
||||||
} else if (parser->model == DSX) {
|
|
||||||
samplesize = 32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int have_temperature = 1, have_pressure = 1;
|
unsigned int have_temperature = 1, have_pressure = 1;
|
||||||
@ -722,8 +666,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
parser->model == I200 || parser->model == I100 ||
|
parser->model == I200 || parser->model == I100 ||
|
||||||
parser->model == I300C || parser->model == TALIS ||
|
parser->model == I300C || parser->model == TALIS ||
|
||||||
parser->model == I200C || parser->model == I200CV2 ||
|
parser->model == I200C || parser->model == I200CV2 ||
|
||||||
parser->model == GEO40 || parser->model == VEO40 ||
|
parser->model == GEO40 || parser->model == VEO40) {
|
||||||
parser->model == I330R) {
|
|
||||||
have_pressure = 0;
|
have_pressure = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -734,7 +677,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initial tank pressure.
|
// Initial tank pressure.
|
||||||
unsigned int tank = 1;
|
unsigned int tank = 0;
|
||||||
unsigned int pressure = 0;
|
unsigned int pressure = 0;
|
||||||
if (have_pressure) {
|
if (have_pressure) {
|
||||||
unsigned int idx = 2;
|
unsigned int idx = 2;
|
||||||
@ -789,17 +732,17 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
if (sampletype == 0xAA) {
|
if (sampletype == 0xAA) {
|
||||||
if (parser->model == DATAMASK || parser->model == COMPUMASK) {
|
if (parser->model == DATAMASK || parser->model == COMPUMASK) {
|
||||||
// Tank pressure (1 psi) and number
|
// Tank pressure (1 psi) and number
|
||||||
tank = 1;
|
tank = 0;
|
||||||
pressure = (((data[offset + 7] << 8) + data[offset + 6]) & 0x0FFF);
|
pressure = (((data[offset + 7] << 8) + data[offset + 6]) & 0x0FFF);
|
||||||
} else if (parser->model == A300CS || parser->model == VTX ||
|
} else if (parser->model == A300CS || parser->model == VTX ||
|
||||||
parser->model == I750TC || parser->model == SAGE ||
|
parser->model == I750TC || parser->model == SAGE ||
|
||||||
parser->model == BEACON) {
|
parser->model == BEACON) {
|
||||||
// Tank pressure (1 psi) and number (one based index)
|
// Tank pressure (1 psi) and number (one based index)
|
||||||
tank = data[offset + 1] & 0x03;
|
tank = (data[offset + 1] & 0x03) - 1;
|
||||||
pressure = ((data[offset + 7] << 8) + data[offset + 6]) & 0x0FFF;
|
pressure = ((data[offset + 7] << 8) + data[offset + 6]) & 0x0FFF;
|
||||||
} else {
|
} else {
|
||||||
// Tank pressure (2 psi) and number (one based index)
|
// Tank pressure (2 psi) and number (one based index)
|
||||||
tank = data[offset + 1] & 0x03;
|
tank = (data[offset + 1] & 0x03) - 1;
|
||||||
if (parser->model == ATOM2 || parser->model == EPICA || parser->model == EPICB)
|
if (parser->model == ATOM2 || parser->model == EPICA || parser->model == EPICB)
|
||||||
pressure = (((data[offset + 3] << 8) + data[offset + 4]) & 0x0FFF) * 2;
|
pressure = (((data[offset + 3] << 8) + data[offset + 4]) & 0x0FFF) * 2;
|
||||||
else
|
else
|
||||||
@ -809,14 +752,14 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
// The surface time is not always a nice multiple of the samplerate.
|
// The surface time is not always a nice multiple of the samplerate.
|
||||||
// The number of inserted surface samples is therefore rounded down
|
// The number of inserted surface samples is therefore rounded down
|
||||||
// to keep the timestamps aligned at multiples of the samplerate.
|
// to keep the timestamps aligned at multiples of the samplerate.
|
||||||
unsigned int surftime = (60 * bcd2dec (data[offset + 1]) + bcd2dec (data[offset + 2])) * 1000;
|
unsigned int surftime = 60 * bcd2dec (data[offset + 1]) + bcd2dec (data[offset + 2]);
|
||||||
unsigned int nsamples = surftime / interval;
|
unsigned int nsamples = surftime / interval;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < nsamples; ++i) {
|
for (unsigned int i = 0; i < nsamples; ++i) {
|
||||||
// Time
|
// Time
|
||||||
time += interval;
|
time += interval;
|
||||||
sample.time = time;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Vendor specific data
|
// Vendor specific data
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
@ -828,18 +771,25 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
|
|
||||||
// Depth
|
// Depth
|
||||||
sample.depth = 0.0;
|
sample.depth = 0.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
complete = 1;
|
complete = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
extratime += surftime;
|
extratime += surftime;
|
||||||
} else {
|
} else {
|
||||||
|
// Skip the extra samples.
|
||||||
|
if ((count % samplerate) != 0) {
|
||||||
|
offset += samplesize;
|
||||||
|
count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Time.
|
// Time.
|
||||||
if (parser->model == I450T || parser->model == I470TC) {
|
if (parser->model == I450T || parser->model == I470TC) {
|
||||||
unsigned int minute = bcd2dec(data[offset + 0]);
|
unsigned int minute = bcd2dec(data[offset + 0]);
|
||||||
unsigned int hour = bcd2dec(data[offset + 1] & 0x0F);
|
unsigned int hour = bcd2dec(data[offset + 1] & 0x0F);
|
||||||
unsigned int second = bcd2dec(data[offset + 2]);
|
unsigned int second = bcd2dec(data[offset + 2]);
|
||||||
unsigned int timestamp = ((hour * 3600) + (minute * 60 ) + second) * 1000 + extratime;
|
unsigned int timestamp = (hour * 3600) + (minute * 60 ) + second + extratime;
|
||||||
if (timestamp < time) {
|
if (timestamp < time) {
|
||||||
ERROR (abstract->context, "Timestamp moved backwards.");
|
ERROR (abstract->context, "Timestamp moved backwards.");
|
||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
@ -853,7 +803,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
time += interval;
|
time += interval;
|
||||||
}
|
}
|
||||||
sample.time = time;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Vendor specific data
|
// Vendor specific data
|
||||||
oceanic_atom2_parser_vendor (parser,
|
oceanic_atom2_parser_vendor (parser,
|
||||||
@ -892,8 +842,6 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
parser->model == I770R|| parser->model == SAGE ||
|
parser->model == I770R|| parser->model == SAGE ||
|
||||||
parser->model == BEACON) {
|
parser->model == BEACON) {
|
||||||
temperature = data[offset + 11];
|
temperature = data[offset + 11];
|
||||||
} else if (parser->model == I330R || parser->model == DSX) {
|
|
||||||
temperature = array_uint16_le(data + offset + 10);
|
|
||||||
} else {
|
} else {
|
||||||
unsigned int sign;
|
unsigned int sign;
|
||||||
if (parser->model == DG03 || parser->model == PROPLUS3 ||
|
if (parser->model == DG03 || parser->model == PROPLUS3 ||
|
||||||
@ -916,12 +864,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
else
|
else
|
||||||
temperature += (data[offset + 7] & 0x0C) >> 2;
|
temperature += (data[offset + 7] & 0x0C) >> 2;
|
||||||
}
|
}
|
||||||
if (parser->model == I330R || parser->model == DSX) {
|
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
||||||
sample.temperature = ((temperature / 10.0) - 32.0) * (5.0 / 9.0);
|
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
} else {
|
|
||||||
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
|
||||||
}
|
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tank Pressure (psi)
|
// Tank Pressure (psi)
|
||||||
@ -945,17 +889,11 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
parser->model == PROPLUSX || parser->model == I770R ||
|
parser->model == PROPLUSX || parser->model == I770R ||
|
||||||
parser->model == SAGE || parser->model == BEACON)
|
parser->model == SAGE || parser->model == BEACON)
|
||||||
pressure = array_uint16_le (data + offset + 4);
|
pressure = array_uint16_le (data + offset + 4);
|
||||||
else if (parser->model == DSX) {
|
else
|
||||||
pressure = array_uint16_le (data + offset + 14);
|
|
||||||
tank = (data[offset] & 0xF0) >> 4;
|
|
||||||
} else {
|
|
||||||
pressure -= data[offset + 1];
|
pressure -= data[offset + 1];
|
||||||
}
|
sample.pressure.tank = tank;
|
||||||
if (tank) {
|
sample.pressure.value = pressure * PSI / BAR;
|
||||||
sample.pressure.tank = tank - 1;
|
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||||
sample.pressure.value = pressure * PSI / BAR;
|
|
||||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Depth (1/16 ft)
|
// Depth (1/16 ft)
|
||||||
@ -973,18 +911,12 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
parser->model == I470TC || parser->model == I200CV2 ||
|
parser->model == I470TC || parser->model == I200CV2 ||
|
||||||
parser->model == GEOAIR)
|
parser->model == GEOAIR)
|
||||||
depth = (data[offset + 4] + (data[offset + 5] << 8)) & 0x0FFF;
|
depth = (data[offset + 4] + (data[offset + 5] << 8)) & 0x0FFF;
|
||||||
else if (parser->model == I330R || parser->model == DSX)
|
|
||||||
depth = array_uint16_le (data + offset + 2);
|
|
||||||
else if (parser->model == ATOM1)
|
else if (parser->model == ATOM1)
|
||||||
depth = data[offset + 3] * 16;
|
depth = data[offset + 3] * 16;
|
||||||
else
|
else
|
||||||
depth = (data[offset + 2] + (data[offset + 3] << 8)) & 0x0FFF;
|
depth = (data[offset + 2] + (data[offset + 3] << 8)) & 0x0FFF;
|
||||||
if (parser->model == I330R || parser->model == DSX) {
|
sample.depth = depth / 16.0 * FEET;
|
||||||
sample.depth = depth / 10.0 * FEET;
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
} else {
|
|
||||||
sample.depth = depth / 16.0 * FEET;
|
|
||||||
}
|
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
|
||||||
|
|
||||||
// Gas mix
|
// Gas mix
|
||||||
unsigned int have_gasmix = 0;
|
unsigned int have_gasmix = 0;
|
||||||
@ -992,17 +924,14 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
if (parser->model == TX1) {
|
if (parser->model == TX1) {
|
||||||
gasmix = data[offset] & 0x07;
|
gasmix = data[offset] & 0x07;
|
||||||
have_gasmix = 1;
|
have_gasmix = 1;
|
||||||
} else if (parser->model == DSX) {
|
|
||||||
gasmix = (data[offset] & 0xF0) >> 4;
|
|
||||||
have_gasmix = 1;
|
|
||||||
}
|
}
|
||||||
if (have_gasmix && gasmix != gasmix_previous && parser->ngasmixes > 0) {
|
if (have_gasmix && gasmix != gasmix_previous) {
|
||||||
if (gasmix < 1 || gasmix > parser->ngasmixes) {
|
if (gasmix < 1 || gasmix > parser->ngasmixes) {
|
||||||
ERROR (abstract->context, "Invalid gas mix index (%u).", gasmix);
|
ERROR (abstract->context, "Invalid gas mix index (%u).", gasmix);
|
||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
}
|
}
|
||||||
sample.gasmix = gasmix - 1;
|
sample.gasmix = gasmix - 1;
|
||||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||||
gasmix_previous = gasmix;
|
gasmix_previous = gasmix;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1026,8 +955,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
have_deco = 1;
|
have_deco = 1;
|
||||||
} else if (parser->model == ATOM31 || parser->model == VISION ||
|
} else if (parser->model == ATOM31 || parser->model == VISION ||
|
||||||
parser->model == XPAIR || parser->model == I550 ||
|
parser->model == XPAIR || parser->model == I550 ||
|
||||||
parser->model == I550C || parser->model == WISDOM4 ||
|
parser->model == I550C || parser->model == WISDOM4) {
|
||||||
parser->model == PROPLUS4 || parser->model == ATMOSAI2) {
|
|
||||||
decostop = (data[offset + 5] & 0xF0) >> 4;
|
decostop = (data[offset + 5] & 0xF0) >> 4;
|
||||||
decotime = array_uint16_le(data + offset + 4) & 0x03FF;
|
decotime = array_uint16_le(data + offset + 4) & 0x03FF;
|
||||||
have_deco = 1;
|
have_deco = 1;
|
||||||
@ -1042,32 +970,17 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
decostop = (data[offset + 7] & 0xF0) >> 4;
|
decostop = (data[offset + 7] & 0xF0) >> 4;
|
||||||
decotime = array_uint16_le(data + offset + 6) & 0x0FFF;
|
decotime = array_uint16_le(data + offset + 6) & 0x0FFF;
|
||||||
have_deco = 1;
|
have_deco = 1;
|
||||||
} else if (parser->model == I330R || parser->model == DSX) {
|
|
||||||
decostop = data[offset + 8];
|
|
||||||
if (decostop) {
|
|
||||||
// Deco time
|
|
||||||
decotime = array_uint16_le(data + offset + 6);
|
|
||||||
} else {
|
|
||||||
// NDL
|
|
||||||
decotime = array_uint16_le(data + offset + 4);
|
|
||||||
}
|
|
||||||
have_deco = 1;
|
|
||||||
}
|
}
|
||||||
if (have_deco) {
|
if (have_deco) {
|
||||||
if (decostop) {
|
if (decostop) {
|
||||||
sample.deco.type = DC_DECO_DECOSTOP;
|
sample.deco.type = DC_DECO_DECOSTOP;
|
||||||
if (parser->model == I330R || parser->model == DSX) {
|
sample.deco.depth = decostop * 10 * FEET;
|
||||||
sample.deco.depth = decostop * FEET;
|
|
||||||
} else {
|
|
||||||
sample.deco.depth = decostop * 10 * FEET;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
sample.deco.type = DC_DECO_NDL;
|
sample.deco.type = DC_DECO_NDL;
|
||||||
sample.deco.depth = 0.0;
|
sample.deco.depth = 0.0;
|
||||||
}
|
}
|
||||||
sample.deco.time = decotime * 60;
|
sample.deco.time = decotime * 60;
|
||||||
sample.deco.tts = 0;
|
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int have_rbt = 0;
|
unsigned int have_rbt = 0;
|
||||||
@ -1084,21 +997,13 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
have_rbt = 1;
|
have_rbt = 1;
|
||||||
} else if (parser->model == VISION || parser->model == XPAIR ||
|
} else if (parser->model == VISION || parser->model == XPAIR ||
|
||||||
parser->model == I550 || parser->model == I550C ||
|
parser->model == I550 || parser->model == I550C ||
|
||||||
parser->model == WISDOM4 || parser->model == PROPLUS4 ||
|
parser->model == WISDOM4) {
|
||||||
parser->model == ATMOSAI2) {
|
|
||||||
rbt = array_uint16_le(data + offset + 6) & 0x03FF;
|
rbt = array_uint16_le(data + offset + 6) & 0x03FF;
|
||||||
have_rbt = 1;
|
have_rbt = 1;
|
||||||
}
|
}
|
||||||
if (have_rbt) {
|
if (have_rbt) {
|
||||||
sample.rbt = rbt;
|
sample.rbt = rbt;
|
||||||
if (callback) callback (DC_SAMPLE_RBT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_RBT, sample, userdata);
|
||||||
}
|
|
||||||
|
|
||||||
// PPO2
|
|
||||||
if (parser->model == I330R) {
|
|
||||||
sample.ppo2.sensor = DC_SENSOR_NONE;
|
|
||||||
sample.ppo2.value = data[offset + 9] / 100.0;
|
|
||||||
if (callback) callback (DC_SAMPLE_PPO2, &sample, userdata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bookmarks
|
// Bookmarks
|
||||||
@ -1113,7 +1018,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
sample.event.time = 0;
|
sample.event.time = 0;
|
||||||
sample.event.flags = 0;
|
sample.event.flags = 0;
|
||||||
sample.event.value = 0;
|
sample.event.value = 0;
|
||||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
|||||||
@ -32,62 +32,72 @@
|
|||||||
|
|
||||||
#define VTABLE(abstract) ((const oceanic_common_device_vtable_t *) abstract->vtable)
|
#define VTABLE(abstract) ((const oceanic_common_device_vtable_t *) abstract->vtable)
|
||||||
|
|
||||||
#define RB_LOGBOOK_DISTANCE(a,b,l,m) ringbuffer_distance (a, b, m, l->rb_logbook_begin, l->rb_logbook_end)
|
#define RB_LOGBOOK_DISTANCE(a,b,l) ringbuffer_distance (a, b, 1, l->rb_logbook_begin, l->rb_logbook_end)
|
||||||
|
#define RB_LOGBOOK_INCR(a,b,l) ringbuffer_increment (a, b, l->rb_logbook_begin, l->rb_logbook_end)
|
||||||
|
|
||||||
#define RB_PROFILE_DISTANCE(a,b,l,m) ringbuffer_distance (a, b, m, l->rb_profile_begin, l->rb_profile_end)
|
#define RB_PROFILE_DISTANCE(a,b,l) ringbuffer_distance (a, b, 0, l->rb_profile_begin, l->rb_profile_end)
|
||||||
|
#define RB_PROFILE_INCR(a,b,l) ringbuffer_increment (a, b, l->rb_profile_begin, l->rb_profile_end)
|
||||||
|
|
||||||
#define INVALID 0
|
#define INVALID 0
|
||||||
|
|
||||||
static dc_status_t
|
static unsigned int
|
||||||
oceanic_common_device_get_profile (const unsigned char data[], const oceanic_common_layout_t *layout, unsigned int *begin, unsigned int *end)
|
get_profile_first (const unsigned char data[], const oceanic_common_layout_t *layout, unsigned int pagesize)
|
||||||
{
|
{
|
||||||
assert (layout != NULL);
|
unsigned int value;
|
||||||
assert (begin != NULL && end != NULL);
|
|
||||||
|
|
||||||
// Get the pagesize
|
|
||||||
unsigned int pagesize = layout->highmem ? 16 * PAGESIZE : PAGESIZE;
|
|
||||||
|
|
||||||
// Get the profile pointers.
|
|
||||||
unsigned int first = 0, last = 0;
|
|
||||||
if (layout->pt_mode_logbook == 0) {
|
if (layout->pt_mode_logbook == 0) {
|
||||||
first = array_uint16_le (data + 5);
|
value = array_uint16_le (data + 5);
|
||||||
last = array_uint16_le (data + 6) >> 4;
|
|
||||||
} else if (layout->pt_mode_logbook == 1) {
|
} else if (layout->pt_mode_logbook == 1) {
|
||||||
first = array_uint16_le (data + 4);
|
value = array_uint16_le (data + 4);
|
||||||
last = array_uint16_le (data + 6);
|
} else if (layout->pt_mode_logbook == 3) {
|
||||||
} else if (layout->pt_mode_logbook == 2 || layout->pt_mode_logbook == 3) {
|
value = array_uint16_le (data + 16);
|
||||||
first = array_uint16_le (data + 16);
|
} else {
|
||||||
last = array_uint16_le (data + 18);
|
return array_uint16_le (data + 16);
|
||||||
} else if (layout->pt_mode_logbook == 4) {
|
|
||||||
first = array_uint32_le (data + 8);
|
|
||||||
last = array_uint32_le (data + 12);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert pages to bytes.
|
unsigned int npages = (layout->memsize - layout->highmem) / pagesize;
|
||||||
if (layout->pt_mode_logbook < 3) {
|
if (npages > 0x4000) {
|
||||||
unsigned int npages = (layout->memsize - layout->highmem) / pagesize;
|
value &= 0x7FFF;
|
||||||
if (npages > 0x4000) {
|
} else if (npages > 0x2000) {
|
||||||
first &= 0x7FFF;
|
value &= 0x3FFF;
|
||||||
last &= 0x7FFF;
|
} else if (npages > 0x1000) {
|
||||||
} else if (npages > 0x2000) {
|
value &= 0x1FFF;
|
||||||
first &= 0x3FFF;
|
} else {
|
||||||
last &= 0x3FFF;
|
value &= 0x0FFF;
|
||||||
} else if (npages > 0x1000) {
|
|
||||||
first &= 0x1FFF;
|
|
||||||
last &= 0x1FFF;
|
|
||||||
} else {
|
|
||||||
first &= 0x0FFF;
|
|
||||||
last &= 0x0FFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
first *= pagesize;
|
|
||||||
last *= pagesize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*begin = layout->highmem + first;
|
return layout->highmem + value * pagesize;
|
||||||
*end = layout->highmem + last + (layout->pt_mode_logbook < 4 ? pagesize : 0);
|
}
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
|
||||||
|
static unsigned int
|
||||||
|
get_profile_last (const unsigned char data[], const oceanic_common_layout_t *layout, unsigned int pagesize)
|
||||||
|
{
|
||||||
|
unsigned int value;
|
||||||
|
|
||||||
|
if (layout->pt_mode_logbook == 0) {
|
||||||
|
value = array_uint16_le (data + 6) >> 4;
|
||||||
|
} else if (layout->pt_mode_logbook == 1) {
|
||||||
|
value = array_uint16_le (data + 6);
|
||||||
|
} else if (layout->pt_mode_logbook == 3) {
|
||||||
|
value = array_uint16_le (data + 18);
|
||||||
|
} else {
|
||||||
|
return array_uint16_le(data + 18);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int npages = (layout->memsize - layout->highmem) / pagesize;
|
||||||
|
|
||||||
|
if (npages > 0x4000) {
|
||||||
|
value &= 0x7FFF;
|
||||||
|
} else if (npages > 0x2000) {
|
||||||
|
value &= 0x3FFF;
|
||||||
|
} else if (npages > 0x1000) {
|
||||||
|
value &= 0x1FFF;
|
||||||
|
} else {
|
||||||
|
value &= 0x0FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
return layout->highmem + value * pagesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -196,11 +206,11 @@ oceanic_common_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
|||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the device info.
|
// Emit a vendor event.
|
||||||
status = VTABLE(abstract)->devinfo (abstract, NULL);
|
dc_event_vendor_t vendor;
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
vendor.data = device->version;
|
||||||
return status;
|
vendor.size = sizeof (device->version);
|
||||||
}
|
device_event_emit (abstract, DC_EVENT_VENDOR, &vendor);
|
||||||
|
|
||||||
// Download the memory dump.
|
// Download the memory dump.
|
||||||
status = device_dump_read (abstract, 0, dc_buffer_get_data (buffer),
|
status = device_dump_read (abstract, 0, dc_buffer_get_data (buffer),
|
||||||
@ -209,43 +219,8 @@ oceanic_common_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
dc_status_t
|
|
||||||
oceanic_common_device_devinfo (dc_device_t *abstract, dc_event_progress_t *progress)
|
|
||||||
{
|
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
|
||||||
oceanic_common_device_t *device = (oceanic_common_device_t *) abstract;
|
|
||||||
|
|
||||||
assert (device != NULL);
|
|
||||||
assert (device->layout != NULL);
|
|
||||||
|
|
||||||
const oceanic_common_layout_t *layout = device->layout;
|
|
||||||
|
|
||||||
// Read the device id.
|
|
||||||
unsigned char id[PAGESIZE] = {0};
|
|
||||||
status = dc_device_read (abstract, layout->cf_devinfo, id, sizeof (id));
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to read the memory page.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update and emit a progress event.
|
|
||||||
if (progress) {
|
|
||||||
progress->current += PAGESIZE;
|
|
||||||
progress->maximum += PAGESIZE;
|
|
||||||
device_event_emit (abstract, DC_EVENT_PROGRESS, progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit a vendor event.
|
|
||||||
dc_event_vendor_t vendor;
|
|
||||||
vendor.data = device->version;
|
|
||||||
vendor.size = sizeof (device->version);
|
|
||||||
device_event_emit (abstract, DC_EVENT_VENDOR, &vendor);
|
|
||||||
|
|
||||||
// Emit a device info event.
|
// Emit a device info event.
|
||||||
|
unsigned char *id = dc_buffer_get_data (buffer) + layout->cf_devinfo;
|
||||||
dc_event_devinfo_t devinfo;
|
dc_event_devinfo_t devinfo;
|
||||||
devinfo.model = array_uint16_be (id + 8);
|
devinfo.model = array_uint16_be (id + 8);
|
||||||
devinfo.firmware = device->firmware;
|
devinfo.firmware = device->firmware;
|
||||||
@ -265,51 +240,7 @@ oceanic_common_device_devinfo (dc_device_t *abstract, dc_event_progress_t *progr
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
oceanic_common_device_pointers (dc_device_t *abstract, dc_event_progress_t *progress,
|
oceanic_common_device_logbook (dc_device_t *abstract, dc_event_progress_t *progress, dc_buffer_t *logbook)
|
||||||
unsigned int *rb_logbook_begin, unsigned int *rb_logbook_end,
|
|
||||||
unsigned int *rb_profile_begin, unsigned int *rb_profile_end)
|
|
||||||
{
|
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
|
||||||
oceanic_common_device_t *device = (oceanic_common_device_t *) abstract;
|
|
||||||
|
|
||||||
assert (device != NULL);
|
|
||||||
assert (device->layout != NULL);
|
|
||||||
assert (rb_logbook_begin != NULL && rb_logbook_end != NULL);
|
|
||||||
assert (rb_profile_begin != NULL && rb_profile_end != NULL);
|
|
||||||
|
|
||||||
const oceanic_common_layout_t *layout = device->layout;
|
|
||||||
|
|
||||||
// Read the pointer data.
|
|
||||||
unsigned char pointers[PAGESIZE] = {0};
|
|
||||||
status = dc_device_read (abstract, layout->cf_pointers, pointers, sizeof (pointers));
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to read the memory page.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update and emit a progress event.
|
|
||||||
if (progress) {
|
|
||||||
progress->current += PAGESIZE;
|
|
||||||
progress->maximum += PAGESIZE;
|
|
||||||
device_event_emit (abstract, DC_EVENT_PROGRESS, progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the pointers.
|
|
||||||
unsigned int rb_logbook_first = array_uint16_le (pointers + 4);
|
|
||||||
unsigned int rb_logbook_last = array_uint16_le (pointers + 6);
|
|
||||||
unsigned int rb_profile_first = array_uint16_le (pointers + 8);
|
|
||||||
unsigned int rb_profile_last = array_uint16_le (pointers + 10);
|
|
||||||
|
|
||||||
*rb_logbook_begin = rb_logbook_first;
|
|
||||||
*rb_logbook_end = rb_logbook_last + (layout->pt_mode_global == 0 ? layout->rb_logbook_entry_size : 0);
|
|
||||||
*rb_profile_begin = rb_profile_first;
|
|
||||||
*rb_profile_end = rb_profile_last;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
dc_status_t
|
|
||||||
oceanic_common_device_logbook (dc_device_t *abstract, dc_event_progress_t *progress, dc_buffer_t *logbook, unsigned int begin, unsigned int end)
|
|
||||||
{
|
{
|
||||||
oceanic_common_device_t *device = (oceanic_common_device_t *) abstract;
|
oceanic_common_device_t *device = (oceanic_common_device_t *) abstract;
|
||||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||||
@ -325,30 +256,37 @@ oceanic_common_device_logbook (dc_device_t *abstract, dc_event_progress_t *progr
|
|||||||
if (!dc_buffer_clear (logbook))
|
if (!dc_buffer_clear (logbook))
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
|
|
||||||
// Validate the logbook pointers.
|
// For devices without a logbook ringbuffer, downloading dives isn't
|
||||||
unsigned int rb_logbook_begin = begin;
|
// possible. This is not considered a fatal error, but handled as if there
|
||||||
unsigned int rb_logbook_end = end;
|
// are no dives present.
|
||||||
if (rb_logbook_begin < layout->rb_logbook_begin ||
|
if (layout->rb_logbook_begin == layout->rb_logbook_end) {
|
||||||
rb_logbook_begin > layout->rb_logbook_end)
|
return DC_STATUS_SUCCESS;
|
||||||
{
|
|
||||||
ERROR (abstract->context, "Invalid logbook begin pointer detected (0x%04x).", rb_logbook_begin);
|
|
||||||
if (layout->rb_logbook_direction == 0) {
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
}
|
|
||||||
// Fall back to downloading the entire logbook ringbuffer as
|
|
||||||
// workaround for an invalid logbook begin pointer!
|
|
||||||
rb_logbook_begin = rb_logbook_end;
|
|
||||||
}
|
}
|
||||||
if (rb_logbook_end < layout->rb_logbook_begin ||
|
|
||||||
rb_logbook_end > layout->rb_logbook_end)
|
// Read the pointer data.
|
||||||
|
unsigned char pointers[PAGESIZE] = {0};
|
||||||
|
rc = dc_device_read (abstract, layout->cf_pointers, pointers, sizeof (pointers));
|
||||||
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
|
ERROR (abstract->context, "Failed to read the memory page.");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the logbook pointers.
|
||||||
|
unsigned int rb_logbook_first = array_uint16_le (pointers + 4);
|
||||||
|
unsigned int rb_logbook_last = array_uint16_le (pointers + 6);
|
||||||
|
if (rb_logbook_last < layout->rb_logbook_begin ||
|
||||||
|
rb_logbook_last >= layout->rb_logbook_end)
|
||||||
{
|
{
|
||||||
ERROR (abstract->context, "Invalid logbook end pointer detected (0x%04x).", rb_logbook_end);
|
ERROR (abstract->context, "Invalid logbook end pointer detected (0x%04x).", rb_logbook_last);
|
||||||
if (layout->rb_logbook_direction != 0) {
|
return DC_STATUS_DATAFORMAT;
|
||||||
return DC_STATUS_DATAFORMAT;
|
}
|
||||||
}
|
|
||||||
// Fall back to downloading the entire logbook ringbuffer as
|
// Calculate the end pointer.
|
||||||
// workaround for an invalid logbook end pointer!
|
unsigned int rb_logbook_end = 0;
|
||||||
rb_logbook_end = rb_logbook_begin;
|
if (layout->pt_mode_global == 0) {
|
||||||
|
rb_logbook_end = RB_LOGBOOK_INCR (rb_logbook_last, layout->rb_logbook_entry_size, layout);
|
||||||
|
} else {
|
||||||
|
rb_logbook_end = rb_logbook_last;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the number of bytes.
|
// Calculate the number of bytes.
|
||||||
@ -357,9 +295,21 @@ oceanic_common_device_logbook (dc_device_t *abstract, dc_event_progress_t *progr
|
|||||||
// full ringbuffer. We always consider the ringbuffer full in that
|
// full ringbuffer. We always consider the ringbuffer full in that
|
||||||
// case, because an empty ringbuffer can be detected by inspecting
|
// case, because an empty ringbuffer can be detected by inspecting
|
||||||
// the logbook entries once they are downloaded.
|
// the logbook entries once they are downloaded.
|
||||||
unsigned int rb_logbook_size = RB_LOGBOOK_DISTANCE (rb_logbook_begin, rb_logbook_end, layout, DC_RINGBUFFER_FULL);
|
unsigned int rb_logbook_size = 0;
|
||||||
|
if (rb_logbook_first < layout->rb_logbook_begin ||
|
||||||
|
rb_logbook_first >= layout->rb_logbook_end)
|
||||||
|
{
|
||||||
|
// Fall back to downloading the entire logbook ringbuffer as
|
||||||
|
// workaround for an invalid logbook begin pointer!
|
||||||
|
ERROR (abstract->context, "Invalid logbook begin pointer detected (0x%04x).", rb_logbook_first);
|
||||||
|
rb_logbook_size = layout->rb_logbook_end - layout->rb_logbook_begin;
|
||||||
|
} else {
|
||||||
|
rb_logbook_size = RB_LOGBOOK_DISTANCE (rb_logbook_first, rb_logbook_end, layout);
|
||||||
|
}
|
||||||
|
|
||||||
// Update and emit a progress event.
|
// Update and emit a progress event.
|
||||||
|
progress->current += PAGESIZE;
|
||||||
|
progress->maximum += PAGESIZE;
|
||||||
progress->maximum -= (layout->rb_logbook_end - layout->rb_logbook_begin) - rb_logbook_size;
|
progress->maximum -= (layout->rb_logbook_end - layout->rb_logbook_begin) - rb_logbook_size;
|
||||||
device_event_emit (abstract, DC_EVENT_PROGRESS, progress);
|
device_event_emit (abstract, DC_EVENT_PROGRESS, progress);
|
||||||
|
|
||||||
@ -377,11 +327,7 @@ oceanic_common_device_logbook (dc_device_t *abstract, dc_event_progress_t *progr
|
|||||||
|
|
||||||
// Create the ringbuffer stream.
|
// Create the ringbuffer stream.
|
||||||
dc_rbstream_t *rbstream = NULL;
|
dc_rbstream_t *rbstream = NULL;
|
||||||
rc = dc_rbstream_new (&rbstream, abstract,
|
rc = dc_rbstream_new (&rbstream, abstract, PAGESIZE, PAGESIZE * device->multipage, layout->rb_logbook_begin, layout->rb_logbook_end, rb_logbook_end);
|
||||||
PAGESIZE, PAGESIZE * device->multipage,
|
|
||||||
layout->rb_logbook_begin, layout->rb_logbook_end,
|
|
||||||
layout->rb_logbook_direction ? rb_logbook_end : rb_logbook_begin,
|
|
||||||
layout->rb_logbook_direction ? DC_RBSTREAM_BACKWARD : DC_RBSTREAM_FORWARD);
|
|
||||||
if (rc != DC_STATUS_SUCCESS) {
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
ERROR (abstract->context, "Failed to create the ringbuffer stream.");
|
ERROR (abstract->context, "Failed to create the ringbuffer stream.");
|
||||||
return rc;
|
return rc;
|
||||||
@ -457,6 +403,9 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr
|
|||||||
|
|
||||||
const oceanic_common_layout_t *layout = device->layout;
|
const oceanic_common_layout_t *layout = device->layout;
|
||||||
|
|
||||||
|
// Get the pagesize
|
||||||
|
unsigned int pagesize = layout->highmem ? 16 * PAGESIZE : PAGESIZE;
|
||||||
|
|
||||||
// Cache the logbook pointer and size.
|
// Cache the logbook pointer and size.
|
||||||
const unsigned char *logbooks = dc_buffer_get_data (logbook);
|
const unsigned char *logbooks = dc_buffer_get_data (logbook);
|
||||||
unsigned int rb_logbook_size = dc_buffer_get_size (logbook);
|
unsigned int rb_logbook_size = dc_buffer_get_size (logbook);
|
||||||
@ -464,7 +413,6 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr
|
|||||||
// Go through the logbook entries a first time, to get the end of
|
// Go through the logbook entries a first time, to get the end of
|
||||||
// profile pointer and calculate the total amount of bytes in the
|
// profile pointer and calculate the total amount of bytes in the
|
||||||
// profile ringbuffer.
|
// profile ringbuffer.
|
||||||
unsigned int rb_profile_begin = INVALID;
|
|
||||||
unsigned int rb_profile_end = INVALID;
|
unsigned int rb_profile_end = INVALID;
|
||||||
unsigned int rb_profile_size = 0;
|
unsigned int rb_profile_size = 0;
|
||||||
|
|
||||||
@ -486,20 +434,22 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the profile pointers.
|
// Get the profile pointers.
|
||||||
unsigned int rb_entry_begin = 0, rb_entry_end = 0;
|
unsigned int rb_entry_first = get_profile_first (logbooks + entry, layout, pagesize);
|
||||||
oceanic_common_device_get_profile (logbooks + entry, layout, &rb_entry_begin, &rb_entry_end);
|
unsigned int rb_entry_last = get_profile_last (logbooks + entry, layout, pagesize);
|
||||||
if (rb_entry_begin < layout->rb_profile_begin ||
|
if (rb_entry_first < layout->rb_profile_begin ||
|
||||||
rb_entry_begin > layout->rb_profile_end ||
|
rb_entry_first >= layout->rb_profile_end ||
|
||||||
rb_entry_end < layout->rb_profile_begin ||
|
rb_entry_last < layout->rb_profile_begin ||
|
||||||
rb_entry_end > layout->rb_profile_end)
|
rb_entry_last >= layout->rb_profile_end)
|
||||||
{
|
{
|
||||||
ERROR (abstract->context, "Invalid ringbuffer pointer detected (0x%06x 0x%06x).",
|
ERROR (abstract->context, "Invalid ringbuffer pointer detected (0x%06x 0x%06x).",
|
||||||
rb_entry_begin, rb_entry_end);
|
rb_entry_first, rb_entry_last);
|
||||||
status = DC_STATUS_DATAFORMAT;
|
status = DC_STATUS_DATAFORMAT;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG (abstract->context, "Entry: %08x %08x", rb_entry_begin, rb_entry_end);
|
// Calculate the end pointer and the number of bytes.
|
||||||
|
unsigned int rb_entry_end = RB_PROFILE_INCR (rb_entry_last, pagesize, layout);
|
||||||
|
unsigned int rb_entry_size = RB_PROFILE_DISTANCE (rb_entry_first, rb_entry_last, layout) + pagesize;
|
||||||
|
|
||||||
// Take the end pointer of the most recent logbook entry as the
|
// Take the end pointer of the most recent logbook entry as the
|
||||||
// end of profile pointer.
|
// end of profile pointer.
|
||||||
@ -507,13 +457,11 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr
|
|||||||
rb_profile_end = previous = rb_entry_end;
|
rb_profile_end = previous = rb_entry_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the number of bytes.
|
|
||||||
unsigned int rb_entry_size = RB_PROFILE_DISTANCE (rb_entry_begin, rb_entry_end, layout, DC_RINGBUFFER_FULL);
|
|
||||||
|
|
||||||
// Skip gaps between the profiles.
|
// Skip gaps between the profiles.
|
||||||
unsigned int gap = RB_PROFILE_DISTANCE (rb_entry_end, previous, layout, DC_RINGBUFFER_EMPTY);
|
unsigned int gap = 0;
|
||||||
if (gap) {
|
if (rb_entry_end != previous) {
|
||||||
WARNING (abstract->context, "Profiles are not continuous (%u bytes).", gap);
|
WARNING (abstract->context, "Profiles are not continuous.");
|
||||||
|
gap = RB_PROFILE_DISTANCE (rb_entry_end, previous, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the profile size is valid.
|
// Make sure the profile size is valid.
|
||||||
@ -522,18 +470,13 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the profile begin pointer.
|
|
||||||
rb_profile_begin = rb_entry_begin;
|
|
||||||
|
|
||||||
// Update the total profile size.
|
// Update the total profile size.
|
||||||
rb_profile_size += rb_entry_size + gap;
|
rb_profile_size += rb_entry_size + gap;
|
||||||
|
|
||||||
remaining -= rb_entry_size + gap;
|
remaining -= rb_entry_size + gap;
|
||||||
previous = rb_entry_begin;
|
previous = rb_entry_first;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG (abstract->context, "Profile: %08x %08x", rb_profile_begin, rb_profile_end);
|
|
||||||
|
|
||||||
// At this point, we know the exact amount of data
|
// At this point, we know the exact amount of data
|
||||||
// that needs to be transfered for the profiles.
|
// that needs to be transfered for the profiles.
|
||||||
progress->maximum -= (layout->rb_profile_end - layout->rb_profile_begin) - rb_profile_size;
|
progress->maximum -= (layout->rb_profile_end - layout->rb_profile_begin) - rb_profile_size;
|
||||||
@ -546,7 +489,7 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr
|
|||||||
|
|
||||||
// Create the ringbuffer stream.
|
// Create the ringbuffer stream.
|
||||||
dc_rbstream_t *rbstream = NULL;
|
dc_rbstream_t *rbstream = NULL;
|
||||||
rc = dc_rbstream_new (&rbstream, abstract, PAGESIZE, PAGESIZE * device->multipage, layout->rb_profile_begin, layout->rb_profile_end, rb_profile_end, DC_RBSTREAM_BACKWARD);
|
rc = dc_rbstream_new (&rbstream, abstract, PAGESIZE, PAGESIZE * device->multipage, layout->rb_profile_begin, layout->rb_profile_end, rb_profile_end);
|
||||||
if (rc != DC_STATUS_SUCCESS) {
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
ERROR (abstract->context, "Failed to create the ringbuffer stream.");
|
ERROR (abstract->context, "Failed to create the ringbuffer stream.");
|
||||||
return rc;
|
return rc;
|
||||||
@ -581,28 +524,28 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the profile pointers.
|
// Get the profile pointers.
|
||||||
unsigned int rb_entry_begin = 0, rb_entry_end = 0;
|
unsigned int rb_entry_first = get_profile_first (logbooks + entry, layout, pagesize);
|
||||||
oceanic_common_device_get_profile (logbooks + entry, layout, &rb_entry_begin, &rb_entry_end);
|
unsigned int rb_entry_last = get_profile_last (logbooks + entry, layout, pagesize);
|
||||||
if (rb_entry_begin < layout->rb_profile_begin ||
|
if (rb_entry_first < layout->rb_profile_begin ||
|
||||||
rb_entry_begin > layout->rb_profile_end ||
|
rb_entry_first >= layout->rb_profile_end ||
|
||||||
rb_entry_end < layout->rb_profile_begin ||
|
rb_entry_last < layout->rb_profile_begin ||
|
||||||
rb_entry_end > layout->rb_profile_end)
|
rb_entry_last >= layout->rb_profile_end)
|
||||||
{
|
{
|
||||||
ERROR (abstract->context, "Invalid ringbuffer pointer detected (0x%06x 0x%06x).",
|
ERROR (abstract->context, "Invalid ringbuffer pointer detected (0x%06x 0x%06x).",
|
||||||
rb_entry_begin, rb_entry_end);
|
rb_entry_first, rb_entry_last);
|
||||||
status = DC_STATUS_DATAFORMAT;
|
status = DC_STATUS_DATAFORMAT;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG (abstract->context, "Entry: %08x %08x", rb_entry_begin, rb_entry_end);
|
// Calculate the end pointer and the number of bytes.
|
||||||
|
unsigned int rb_entry_end = RB_PROFILE_INCR (rb_entry_last, pagesize, layout);
|
||||||
// Calculate the number of bytes.
|
unsigned int rb_entry_size = RB_PROFILE_DISTANCE (rb_entry_first, rb_entry_last, layout) + pagesize;
|
||||||
unsigned int rb_entry_size = RB_PROFILE_DISTANCE (rb_entry_begin, rb_entry_end, layout, DC_RINGBUFFER_FULL);
|
|
||||||
|
|
||||||
// Skip gaps between the profiles.
|
// Skip gaps between the profiles.
|
||||||
unsigned int gap = RB_PROFILE_DISTANCE (rb_entry_end, previous, layout, DC_RINGBUFFER_EMPTY);
|
unsigned int gap = 0;
|
||||||
if (gap) {
|
if (rb_entry_end != previous) {
|
||||||
WARNING (abstract->context, "Profiles are not continuous (%u bytes).", gap);
|
WARNING (abstract->context, "Profiles are not continuous.");
|
||||||
|
gap = RB_PROFILE_DISTANCE (rb_entry_end, previous, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the profile size is valid.
|
// Make sure the profile size is valid.
|
||||||
@ -623,7 +566,7 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr
|
|||||||
}
|
}
|
||||||
|
|
||||||
remaining -= rb_entry_size + gap;
|
remaining -= rb_entry_size + gap;
|
||||||
previous = rb_entry_begin;
|
previous = rb_entry_first;
|
||||||
|
|
||||||
// Prepend the logbook entry to the profile data. The memory buffer is
|
// Prepend the logbook entry to the profile data. The memory buffer is
|
||||||
// large enough to store this entry.
|
// large enough to store this entry.
|
||||||
@ -661,7 +604,6 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr
|
|||||||
dc_status_t
|
dc_status_t
|
||||||
oceanic_common_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata)
|
oceanic_common_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata)
|
||||||
{
|
{
|
||||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
|
||||||
oceanic_common_device_t *device = (oceanic_common_device_t *) abstract;
|
oceanic_common_device_t *device = (oceanic_common_device_t *) abstract;
|
||||||
|
|
||||||
assert (device != NULL);
|
assert (device != NULL);
|
||||||
@ -669,37 +611,45 @@ oceanic_common_device_foreach (dc_device_t *abstract, dc_dive_callback_t callbac
|
|||||||
|
|
||||||
const oceanic_common_layout_t *layout = device->layout;
|
const oceanic_common_layout_t *layout = device->layout;
|
||||||
|
|
||||||
// For devices without a logbook and profile ringbuffer, downloading dives
|
|
||||||
// isn't possible. This is not considered a fatal error, but handled as if
|
|
||||||
// there are no dives present.
|
|
||||||
if (layout->rb_logbook_begin == layout->rb_logbook_end &&
|
|
||||||
layout->rb_profile_begin == layout->rb_profile_end) {
|
|
||||||
return DC_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable progress notifications.
|
// Enable progress notifications.
|
||||||
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
|
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
|
||||||
progress.maximum =
|
progress.maximum = PAGESIZE +
|
||||||
(layout->rb_logbook_end - layout->rb_logbook_begin) +
|
(layout->rb_logbook_end - layout->rb_logbook_begin) +
|
||||||
(layout->rb_profile_end - layout->rb_profile_begin);
|
(layout->rb_profile_end - layout->rb_profile_begin);
|
||||||
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
|
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
|
||||||
|
|
||||||
// Read the device info.
|
// Emit a vendor event.
|
||||||
rc = VTABLE(abstract)->devinfo (abstract, &progress);
|
dc_event_vendor_t vendor;
|
||||||
|
vendor.data = device->version;
|
||||||
|
vendor.size = sizeof (device->version);
|
||||||
|
device_event_emit (abstract, DC_EVENT_VENDOR, &vendor);
|
||||||
|
|
||||||
|
// Read the device id.
|
||||||
|
unsigned char id[PAGESIZE] = {0};
|
||||||
|
dc_status_t rc = dc_device_read (abstract, layout->cf_devinfo, id, sizeof (id));
|
||||||
if (rc != DC_STATUS_SUCCESS) {
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
|
ERROR (abstract->context, "Failed to read the memory page.");
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the ringbuffer pointers.
|
// Update and emit a progress event.
|
||||||
unsigned int rb_logbook_begin = 0, rb_logbook_end = 0;
|
progress.current += PAGESIZE;
|
||||||
unsigned int rb_profile_begin = 0, rb_profile_end = 0;
|
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
|
||||||
rc = VTABLE(abstract)->pointers (abstract, &progress, &rb_logbook_begin, &rb_logbook_end, &rb_profile_begin, &rb_profile_end);
|
|
||||||
if (rc != DC_STATUS_SUCCESS) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG (abstract->context, "Logbook: %08x %08x", rb_logbook_begin, rb_logbook_end);
|
// Emit a device info event.
|
||||||
DEBUG (abstract->context, "Profile: %08x %08x", rb_profile_begin, rb_profile_end);
|
dc_event_devinfo_t devinfo;
|
||||||
|
devinfo.model = array_uint16_be (id + 8);
|
||||||
|
devinfo.firmware = device->firmware;
|
||||||
|
if (layout->pt_mode_serial == 0)
|
||||||
|
devinfo.serial = array_convert_bcd2dec (id + 10, 3);
|
||||||
|
else if (layout->pt_mode_serial == 1)
|
||||||
|
devinfo.serial = array_convert_bin2dec (id + 11, 3);
|
||||||
|
else
|
||||||
|
devinfo.serial =
|
||||||
|
(id[11] & 0x0F) * 100000 + ((id[11] & 0xF0) >> 4) * 10000 +
|
||||||
|
(id[12] & 0x0F) * 1000 + ((id[12] & 0xF0) >> 4) * 100 +
|
||||||
|
(id[13] & 0x0F) * 10 + ((id[13] & 0xF0) >> 4) * 1;
|
||||||
|
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);
|
||||||
|
|
||||||
// Memory buffer for the logbook data.
|
// Memory buffer for the logbook data.
|
||||||
dc_buffer_t *logbook = dc_buffer_new (0);
|
dc_buffer_t *logbook = dc_buffer_new (0);
|
||||||
@ -708,7 +658,7 @@ oceanic_common_device_foreach (dc_device_t *abstract, dc_dive_callback_t callbac
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Download the logbook ringbuffer.
|
// Download the logbook ringbuffer.
|
||||||
rc = VTABLE(abstract)->logbook (abstract, &progress, logbook, rb_logbook_begin, rb_logbook_end);
|
rc = VTABLE(abstract)->logbook (abstract, &progress, logbook);
|
||||||
if (rc != DC_STATUS_SUCCESS) {
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
dc_buffer_free (logbook);
|
dc_buffer_free (logbook);
|
||||||
return rc;
|
return rc;
|
||||||
|
|||||||
@ -125,12 +125,8 @@ extern "C" {
|
|||||||
#define I200CV2 0x4749
|
#define I200CV2 0x4749
|
||||||
#define GEOAIR 0x474B
|
#define GEOAIR 0x474B
|
||||||
|
|
||||||
// i330r
|
|
||||||
#define DSX 0x4741
|
|
||||||
#define I330R 0x4744
|
|
||||||
|
|
||||||
#define PAGESIZE 0x10
|
#define PAGESIZE 0x10
|
||||||
#define FPMAXSIZE 0x200
|
#define FPMAXSIZE 0x20
|
||||||
|
|
||||||
#define OCEANIC_COMMON_MATCH(version,patterns,firmware) \
|
#define OCEANIC_COMMON_MATCH(version,patterns,firmware) \
|
||||||
oceanic_common_match ((version), (patterns), \
|
oceanic_common_match ((version), (patterns), \
|
||||||
@ -148,7 +144,6 @@ typedef struct oceanic_common_layout_t {
|
|||||||
unsigned int rb_logbook_begin;
|
unsigned int rb_logbook_begin;
|
||||||
unsigned int rb_logbook_end;
|
unsigned int rb_logbook_end;
|
||||||
unsigned int rb_logbook_entry_size;
|
unsigned int rb_logbook_entry_size;
|
||||||
unsigned int rb_logbook_direction;
|
|
||||||
// Profile ringbuffer
|
// Profile ringbuffer
|
||||||
unsigned int rb_profile_begin;
|
unsigned int rb_profile_begin;
|
||||||
unsigned int rb_profile_end;
|
unsigned int rb_profile_end;
|
||||||
@ -173,9 +168,7 @@ typedef struct oceanic_common_device_t {
|
|||||||
|
|
||||||
typedef struct oceanic_common_device_vtable_t {
|
typedef struct oceanic_common_device_vtable_t {
|
||||||
dc_device_vtable_t base;
|
dc_device_vtable_t base;
|
||||||
dc_status_t (*devinfo) (dc_device_t *device, dc_event_progress_t *progress);
|
dc_status_t (*logbook) (dc_device_t *device, dc_event_progress_t *progress, dc_buffer_t *logbook);
|
||||||
dc_status_t (*pointers) (dc_device_t *device, dc_event_progress_t *progress, unsigned int *rb_logbook_begin, unsigned int *rb_logbook_end, unsigned int *rb_profile_begin, unsigned int *rb_profile_end);
|
|
||||||
dc_status_t (*logbook) (dc_device_t *device, dc_event_progress_t *progress, dc_buffer_t *logbook, unsigned int begin, unsigned int end);
|
|
||||||
dc_status_t (*profile) (dc_device_t *device, dc_event_progress_t *progress, dc_buffer_t *logbook, dc_dive_callback_t callback, void *userdata);
|
dc_status_t (*profile) (dc_device_t *device, dc_event_progress_t *progress, dc_buffer_t *logbook, dc_dive_callback_t callback, void *userdata);
|
||||||
} oceanic_common_device_vtable_t;
|
} oceanic_common_device_vtable_t;
|
||||||
|
|
||||||
@ -193,15 +186,7 @@ void
|
|||||||
oceanic_common_device_init (oceanic_common_device_t *device);
|
oceanic_common_device_init (oceanic_common_device_t *device);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
oceanic_common_device_devinfo (dc_device_t *device, dc_event_progress_t *progress);
|
oceanic_common_device_logbook (dc_device_t *device, dc_event_progress_t *progress, dc_buffer_t *logbook);
|
||||||
|
|
||||||
dc_status_t
|
|
||||||
oceanic_common_device_pointers (dc_device_t *device, dc_event_progress_t *progress,
|
|
||||||
unsigned int *rb_logbook_begin, unsigned int *rb_logbook_end,
|
|
||||||
unsigned int *rb_profile_begin, unsigned int *rb_profile_end);
|
|
||||||
|
|
||||||
dc_status_t
|
|
||||||
oceanic_common_device_logbook (dc_device_t *device, dc_event_progress_t *progress, dc_buffer_t *logbook, unsigned int begin, unsigned int end);
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
oceanic_common_device_profile (dc_device_t *device, dc_event_progress_t *progress, dc_buffer_t *logbook, dc_dive_callback_t callback, void *userdata);
|
oceanic_common_device_profile (dc_device_t *device, dc_event_progress_t *progress, dc_buffer_t *logbook, dc_dive_callback_t callback, void *userdata);
|
||||||
|
|||||||
@ -58,8 +58,6 @@ static const oceanic_common_device_vtable_t oceanic_veo250_device_vtable = {
|
|||||||
NULL, /* timesync */
|
NULL, /* timesync */
|
||||||
oceanic_veo250_device_close /* close */
|
oceanic_veo250_device_close /* close */
|
||||||
},
|
},
|
||||||
oceanic_common_device_devinfo,
|
|
||||||
oceanic_common_device_pointers,
|
|
||||||
oceanic_common_device_logbook,
|
oceanic_common_device_logbook,
|
||||||
oceanic_common_device_profile,
|
oceanic_common_device_profile,
|
||||||
};
|
};
|
||||||
@ -72,7 +70,6 @@ static const oceanic_common_layout_t oceanic_veo250_layout = {
|
|||||||
0x0400, /* rb_logbook_begin */
|
0x0400, /* rb_logbook_begin */
|
||||||
0x0600, /* rb_logbook_end */
|
0x0600, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x0600, /* rb_profile_begin */
|
0x0600, /* rb_profile_begin */
|
||||||
0x8000, /* rb_profile_end */
|
0x8000, /* rb_profile_end */
|
||||||
1, /* pt_mode_global */
|
1, /* pt_mode_global */
|
||||||
|
|||||||
@ -37,7 +37,7 @@ dc_status_t
|
|||||||
oceanic_veo250_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
oceanic_veo250_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
oceanic_veo250_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
oceanic_veo250_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,6 +42,7 @@ struct oceanic_veo250_parser_t {
|
|||||||
double maxdepth;
|
double maxdepth;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static dc_status_t oceanic_veo250_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t oceanic_veo250_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t oceanic_veo250_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t oceanic_veo250_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t oceanic_veo250_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -49,6 +50,7 @@ static dc_status_t oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract,
|
|||||||
static const dc_parser_vtable_t oceanic_veo250_parser_vtable = {
|
static const dc_parser_vtable_t oceanic_veo250_parser_vtable = {
|
||||||
sizeof(oceanic_veo250_parser_t),
|
sizeof(oceanic_veo250_parser_t),
|
||||||
DC_FAMILY_OCEANIC_VEO250,
|
DC_FAMILY_OCEANIC_VEO250,
|
||||||
|
oceanic_veo250_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -60,7 +62,7 @@ static const dc_parser_vtable_t oceanic_veo250_parser_vtable = {
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
oceanic_veo250_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
oceanic_veo250_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||||
{
|
{
|
||||||
oceanic_veo250_parser_t *parser = NULL;
|
oceanic_veo250_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -68,7 +70,7 @@ oceanic_veo250_parser_create (dc_parser_t **out, dc_context_t *context, const un
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (oceanic_veo250_parser_t *) dc_parser_allocate (context, &oceanic_veo250_parser_vtable, data, size);
|
parser = (oceanic_veo250_parser_t *) dc_parser_allocate (context, &oceanic_veo250_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -86,6 +88,20 @@ oceanic_veo250_parser_create (dc_parser_t **out, dc_context_t *context, const un
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
oceanic_veo250_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
oceanic_veo250_parser_t *parser = (oceanic_veo250_parser_t *) abstract;
|
||||||
|
|
||||||
|
// Reset the cache.
|
||||||
|
parser->cached = 0;
|
||||||
|
parser->divetime = 0;
|
||||||
|
parser->maxdepth = 0.0;
|
||||||
|
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
oceanic_veo250_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
oceanic_veo250_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -154,7 +170,6 @@ oceanic_veo250_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
|
|||||||
*((unsigned int *) value) = 1;
|
*((unsigned int *) value) = 1;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
gasmix->helium = 0.0;
|
gasmix->helium = 0.0;
|
||||||
if (data[footer + 6])
|
if (data[footer + 6])
|
||||||
gasmix->oxygen = data[footer + 6] / 100.0;
|
gasmix->oxygen = data[footer + 6] / 100.0;
|
||||||
@ -215,19 +230,19 @@ oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
|||||||
|
|
||||||
// Time.
|
// Time.
|
||||||
time += interval;
|
time += interval;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Vendor specific data
|
// Vendor specific data
|
||||||
sample.vendor.type = SAMPLE_VENDOR_OCEANIC_VEO250;
|
sample.vendor.type = SAMPLE_VENDOR_OCEANIC_VEO250;
|
||||||
sample.vendor.size = PAGESIZE / 2;
|
sample.vendor.size = PAGESIZE / 2;
|
||||||
sample.vendor.data = data + offset;
|
sample.vendor.data = data + offset;
|
||||||
if (callback) callback (DC_SAMPLE_VENDOR, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_VENDOR, sample, userdata);
|
||||||
|
|
||||||
// Depth (ft)
|
// Depth (ft)
|
||||||
unsigned int depth = data[offset + 2];
|
unsigned int depth = data[offset + 2];
|
||||||
sample.depth = depth * FEET;
|
sample.depth = depth * FEET;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
// Temperature (°F)
|
// Temperature (°F)
|
||||||
unsigned int temperature;
|
unsigned int temperature;
|
||||||
@ -238,7 +253,7 @@ oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
|||||||
temperature = data[offset + 7];
|
temperature = data[offset + 7];
|
||||||
}
|
}
|
||||||
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
|
|
||||||
// NDL / Deco
|
// NDL / Deco
|
||||||
unsigned int have_deco = 0;
|
unsigned int have_deco = 0;
|
||||||
@ -262,8 +277,7 @@ oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
|||||||
sample.deco.depth = 0.0;
|
sample.deco.depth = 0.0;
|
||||||
}
|
}
|
||||||
sample.deco.time = decotime * 60;
|
sample.deco.time = decotime * 60;
|
||||||
sample.deco.tts = 0;
|
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += PAGESIZE / 2;
|
offset += PAGESIZE / 2;
|
||||||
|
|||||||
@ -51,8 +51,7 @@ typedef struct oceanic_vtpro_device_t {
|
|||||||
oceanic_vtpro_protocol_t protocol;
|
oceanic_vtpro_protocol_t protocol;
|
||||||
} oceanic_vtpro_device_t;
|
} oceanic_vtpro_device_t;
|
||||||
|
|
||||||
static dc_status_t oceanic_vtpro_device_pointers (dc_device_t *abstract, dc_event_progress_t *progress, unsigned int *rb_logbook_begin, unsigned int *rb_logbook_end, unsigned int *rb_profile_begin, unsigned int *rb_profile_end);
|
static dc_status_t oceanic_vtpro_device_logbook (dc_device_t *abstract, dc_event_progress_t *progress, dc_buffer_t *logbook);
|
||||||
static dc_status_t oceanic_vtpro_device_logbook (dc_device_t *abstract, dc_event_progress_t *progress, dc_buffer_t *logbook, unsigned int begin, unsigned int end);
|
|
||||||
static dc_status_t oceanic_vtpro_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size);
|
static dc_status_t oceanic_vtpro_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size);
|
||||||
static dc_status_t oceanic_vtpro_device_close (dc_device_t *abstract);
|
static dc_status_t oceanic_vtpro_device_close (dc_device_t *abstract);
|
||||||
|
|
||||||
@ -68,8 +67,6 @@ static const oceanic_common_device_vtable_t oceanic_vtpro_device_vtable = {
|
|||||||
NULL, /* timesync */
|
NULL, /* timesync */
|
||||||
oceanic_vtpro_device_close /* close */
|
oceanic_vtpro_device_close /* close */
|
||||||
},
|
},
|
||||||
oceanic_common_device_devinfo,
|
|
||||||
oceanic_vtpro_device_pointers,
|
|
||||||
oceanic_vtpro_device_logbook,
|
oceanic_vtpro_device_logbook,
|
||||||
oceanic_common_device_profile,
|
oceanic_common_device_profile,
|
||||||
};
|
};
|
||||||
@ -82,7 +79,6 @@ static const oceanic_common_layout_t oceanic_vtpro_layout = {
|
|||||||
0x0240, /* rb_logbook_begin */
|
0x0240, /* rb_logbook_begin */
|
||||||
0x0440, /* rb_logbook_end */
|
0x0440, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x0440, /* rb_profile_begin */
|
0x0440, /* rb_profile_begin */
|
||||||
0x8000, /* rb_profile_end */
|
0x8000, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -98,7 +94,6 @@ static const oceanic_common_layout_t oceanic_wisdom_layout = {
|
|||||||
0x03D0, /* rb_logbook_begin */
|
0x03D0, /* rb_logbook_begin */
|
||||||
0x05D0, /* rb_logbook_end */
|
0x05D0, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x05D0, /* rb_profile_begin */
|
0x05D0, /* rb_profile_begin */
|
||||||
0x8000, /* rb_profile_end */
|
0x8000, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -114,7 +109,6 @@ static const oceanic_common_layout_t aeris_500ai_layout = {
|
|||||||
0x0200, /* rb_logbook_begin */
|
0x0200, /* rb_logbook_begin */
|
||||||
0x0200, /* rb_logbook_end */
|
0x0200, /* rb_logbook_end */
|
||||||
8, /* rb_logbook_entry_size */
|
8, /* rb_logbook_entry_size */
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x00200, /* rb_profile_begin */
|
0x00200, /* rb_profile_begin */
|
||||||
0x20000, /* rb_profile_end */
|
0x20000, /* rb_profile_end */
|
||||||
0, /* pt_mode_global */
|
0, /* pt_mode_global */
|
||||||
@ -292,49 +286,7 @@ oceanic_vtpro_calibrate (oceanic_vtpro_device_t *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
oceanic_aeris500ai_device_pointers (dc_device_t *abstract, dc_event_progress_t *progress, unsigned int *rb_logbook_begin, unsigned int *rb_logbook_end, unsigned int *rb_profile_begin, unsigned int *rb_profile_end)
|
oceanic_aeris500ai_device_logbook (dc_device_t *abstract, dc_event_progress_t *progress, dc_buffer_t *logbook)
|
||||||
{
|
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
|
||||||
oceanic_vtpro_device_t *device = (oceanic_vtpro_device_t *) abstract;
|
|
||||||
|
|
||||||
assert (device != NULL);
|
|
||||||
assert (device->base.layout != NULL);
|
|
||||||
assert (rb_logbook_begin != NULL && rb_logbook_end != NULL);
|
|
||||||
assert (rb_profile_begin != NULL && rb_profile_end != NULL);
|
|
||||||
|
|
||||||
const oceanic_common_layout_t *layout = device->base.layout;
|
|
||||||
|
|
||||||
// Read the pointer data.
|
|
||||||
unsigned char pointers[PAGESIZE] = {0};
|
|
||||||
status = oceanic_vtpro_device_read (abstract, layout->cf_pointers, pointers, sizeof (pointers));
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to read the memory page.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update and emit a progress event.
|
|
||||||
if (progress) {
|
|
||||||
progress->current += PAGESIZE;
|
|
||||||
progress->maximum += PAGESIZE;
|
|
||||||
device_event_emit (abstract, DC_EVENT_PROGRESS, progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the pointers.
|
|
||||||
unsigned int rb_logbook_first = pointers[0x02];
|
|
||||||
unsigned int rb_logbook_last = pointers[0x03];
|
|
||||||
unsigned int rb_profile_first = array_uint16_le (pointers + 4) * PAGESIZE;
|
|
||||||
unsigned int rb_profile_last = array_uint16_le (pointers + 6) * PAGESIZE;
|
|
||||||
|
|
||||||
*rb_logbook_begin = rb_logbook_first;
|
|
||||||
*rb_logbook_end = rb_logbook_last;
|
|
||||||
*rb_profile_begin = rb_profile_first;
|
|
||||||
*rb_profile_end = rb_profile_last;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
oceanic_aeris500ai_device_logbook (dc_device_t *abstract, dc_event_progress_t *progress, dc_buffer_t *logbook, unsigned int begin, unsigned int end)
|
|
||||||
{
|
{
|
||||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||||
oceanic_vtpro_device_t *device = (oceanic_vtpro_device_t *) abstract;
|
oceanic_vtpro_device_t *device = (oceanic_vtpro_device_t *) abstract;
|
||||||
@ -345,25 +297,36 @@ oceanic_aeris500ai_device_logbook (dc_device_t *abstract, dc_event_progress_t *p
|
|||||||
assert (device->base.layout->rb_logbook_begin == device->base.layout->rb_logbook_end);
|
assert (device->base.layout->rb_logbook_begin == device->base.layout->rb_logbook_end);
|
||||||
assert (progress != NULL);
|
assert (progress != NULL);
|
||||||
|
|
||||||
|
const oceanic_common_layout_t *layout = device->base.layout;
|
||||||
|
|
||||||
// Erase the buffer.
|
// Erase the buffer.
|
||||||
if (!dc_buffer_clear (logbook))
|
if (!dc_buffer_clear (logbook))
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
|
|
||||||
// Get the number of dives.
|
// Read the pointer data.
|
||||||
unsigned int ndives = end - begin + 1;
|
unsigned char pointers[PAGESIZE] = {0};
|
||||||
|
rc = oceanic_vtpro_device_read (abstract, layout->cf_pointers, pointers, sizeof (pointers));
|
||||||
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
|
ERROR (abstract->context, "Failed to read the memory page.");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the logbook pointers.
|
||||||
|
unsigned int last = pointers[0x03];
|
||||||
|
|
||||||
// Update and emit a progress event.
|
// Update and emit a progress event.
|
||||||
progress->maximum += ndives * PAGESIZE / 2;
|
progress->current += PAGESIZE;
|
||||||
|
progress->maximum += PAGESIZE + (last + 1) * PAGESIZE / 2;
|
||||||
device_event_emit (abstract, DC_EVENT_PROGRESS, progress);
|
device_event_emit (abstract, DC_EVENT_PROGRESS, progress);
|
||||||
|
|
||||||
// Allocate memory for the logbook entries.
|
// Allocate memory for the logbook entries.
|
||||||
if (!dc_buffer_reserve (logbook, ndives * PAGESIZE / 2))
|
if (!dc_buffer_reserve (logbook, (last + 1) * PAGESIZE / 2))
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
|
|
||||||
// Send the logbook index command.
|
// Send the logbook index command.
|
||||||
unsigned char command[] = {0x52,
|
unsigned char command[] = {0x52,
|
||||||
begin & 0xFF,
|
(last >> 8) & 0xFF, // high
|
||||||
end & 0xFF,
|
(last ) & 0xFF, // low
|
||||||
0x00};
|
0x00};
|
||||||
rc = oceanic_vtpro_transfer (device, command, sizeof (command), NULL, 0);
|
rc = oceanic_vtpro_transfer (device, command, sizeof (command), NULL, 0);
|
||||||
if (rc != DC_STATUS_SUCCESS) {
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
@ -372,7 +335,7 @@ oceanic_aeris500ai_device_logbook (dc_device_t *abstract, dc_event_progress_t *p
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read the logbook index.
|
// Read the logbook index.
|
||||||
for (unsigned int i = 0; i < ndives; ++i) {
|
for (unsigned int i = 0; i < last + 1; ++i) {
|
||||||
// Receive the answer of the dive computer.
|
// Receive the answer of the dive computer.
|
||||||
unsigned char answer[PAGESIZE / 2 + 1] = {0};
|
unsigned char answer[PAGESIZE / 2 + 1] = {0};
|
||||||
rc = dc_iostream_read (device->iostream, answer, sizeof(answer), NULL);
|
rc = dc_iostream_read (device->iostream, answer, sizeof(answer), NULL);
|
||||||
@ -411,26 +374,14 @@ oceanic_aeris500ai_device_logbook (dc_device_t *abstract, dc_event_progress_t *p
|
|||||||
}
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
oceanic_vtpro_device_pointers (dc_device_t *abstract, dc_event_progress_t *progress, unsigned int *rb_logbook_begin, unsigned int *rb_logbook_end, unsigned int *rb_profile_begin, unsigned int *rb_profile_end)
|
oceanic_vtpro_device_logbook (dc_device_t *abstract, dc_event_progress_t *progress, dc_buffer_t *logbook)
|
||||||
{
|
{
|
||||||
oceanic_vtpro_device_t *device = (oceanic_vtpro_device_t *) abstract;
|
oceanic_vtpro_device_t *device = (oceanic_vtpro_device_t *) abstract;
|
||||||
|
|
||||||
if (device->base.model == AERIS500AI) {
|
if (device->base.model == AERIS500AI) {
|
||||||
return oceanic_aeris500ai_device_pointers (abstract, progress, rb_logbook_begin, rb_logbook_end, rb_profile_begin, rb_profile_end);
|
return oceanic_aeris500ai_device_logbook (abstract, progress, logbook);
|
||||||
} else {
|
} else {
|
||||||
return oceanic_common_device_pointers (abstract, progress, rb_logbook_begin, rb_logbook_end, rb_profile_begin, rb_profile_end);
|
return oceanic_common_device_logbook (abstract, progress, logbook);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
oceanic_vtpro_device_logbook (dc_device_t *abstract, dc_event_progress_t *progress, dc_buffer_t *logbook, unsigned int begin, unsigned int end)
|
|
||||||
{
|
|
||||||
oceanic_vtpro_device_t *device = (oceanic_vtpro_device_t *) abstract;
|
|
||||||
|
|
||||||
if (device->base.model == AERIS500AI) {
|
|
||||||
return oceanic_aeris500ai_device_logbook (abstract, progress, logbook, begin, end);
|
|
||||||
} else {
|
|
||||||
return oceanic_common_device_logbook (abstract, progress, logbook, begin, end);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -37,7 +37,7 @@ dc_status_t
|
|||||||
oceanic_vtpro_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
oceanic_vtpro_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
oceanic_vtpro_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
oceanic_vtpro_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,6 +42,7 @@ struct oceanic_vtpro_parser_t {
|
|||||||
double maxdepth;
|
double maxdepth;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static dc_status_t oceanic_vtpro_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t oceanic_vtpro_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t oceanic_vtpro_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t oceanic_vtpro_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t oceanic_vtpro_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -49,6 +50,7 @@ static dc_status_t oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract,
|
|||||||
static const dc_parser_vtable_t oceanic_vtpro_parser_vtable = {
|
static const dc_parser_vtable_t oceanic_vtpro_parser_vtable = {
|
||||||
sizeof(oceanic_vtpro_parser_t),
|
sizeof(oceanic_vtpro_parser_t),
|
||||||
DC_FAMILY_OCEANIC_VTPRO,
|
DC_FAMILY_OCEANIC_VTPRO,
|
||||||
|
oceanic_vtpro_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -60,7 +62,7 @@ static const dc_parser_vtable_t oceanic_vtpro_parser_vtable = {
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
oceanic_vtpro_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
oceanic_vtpro_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||||
{
|
{
|
||||||
oceanic_vtpro_parser_t *parser = NULL;
|
oceanic_vtpro_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -68,7 +70,7 @@ oceanic_vtpro_parser_create (dc_parser_t **out, dc_context_t *context, const uns
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (oceanic_vtpro_parser_t *) dc_parser_allocate (context, &oceanic_vtpro_parser_vtable, data, size);
|
parser = (oceanic_vtpro_parser_t *) dc_parser_allocate (context, &oceanic_vtpro_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -86,6 +88,20 @@ oceanic_vtpro_parser_create (dc_parser_t **out, dc_context_t *context, const uns
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
oceanic_vtpro_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
oceanic_vtpro_parser_t *parser = (oceanic_vtpro_parser_t *) abstract;
|
||||||
|
|
||||||
|
// Reset the cache.
|
||||||
|
parser->cached = 0;
|
||||||
|
parser->divetime = 0;
|
||||||
|
parser->maxdepth = 0.0;
|
||||||
|
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
oceanic_vtpro_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
oceanic_vtpro_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -184,7 +200,6 @@ oceanic_vtpro_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns
|
|||||||
*((unsigned int *) value) = 1;
|
*((unsigned int *) value) = 1;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
gasmix->helium = 0.0;
|
gasmix->helium = 0.0;
|
||||||
if (oxygen)
|
if (oxygen)
|
||||||
gasmix->oxygen = oxygen / 100.0;
|
gasmix->oxygen = oxygen / 100.0;
|
||||||
@ -205,7 +220,6 @@ oceanic_vtpro_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns
|
|||||||
tank->gasmix = flags;
|
tank->gasmix = flags;
|
||||||
tank->beginpressure = beginpressure * 2 * PSI / BAR;
|
tank->beginpressure = beginpressure * 2 * PSI / BAR;
|
||||||
tank->endpressure = endpressure * 2 * PSI / BAR;
|
tank->endpressure = endpressure * 2 * PSI / BAR;
|
||||||
tank->usage = DC_USAGE_NONE;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return DC_STATUS_UNSUPPORTED;
|
return DC_STATUS_UNSUPPORTED;
|
||||||
@ -317,14 +331,14 @@ oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
time = timestamp * 60 + (i + 1) * interval;
|
time = timestamp * 60 + (i + 1) * interval;
|
||||||
else
|
else
|
||||||
time = timestamp * 60 + (i + 1) * 60.0 / count + 0.5;
|
time = timestamp * 60 + (i + 1) * 60.0 / count + 0.5;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Vendor specific data
|
// Vendor specific data
|
||||||
sample.vendor.type = SAMPLE_VENDOR_OCEANIC_VTPRO;
|
sample.vendor.type = SAMPLE_VENDOR_OCEANIC_VTPRO;
|
||||||
sample.vendor.size = PAGESIZE / 2;
|
sample.vendor.size = PAGESIZE / 2;
|
||||||
sample.vendor.data = data + offset;
|
sample.vendor.data = data + offset;
|
||||||
if (callback) callback (DC_SAMPLE_VENDOR, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_VENDOR, sample, userdata);
|
||||||
|
|
||||||
// Depth (ft)
|
// Depth (ft)
|
||||||
unsigned int depth = 0;
|
unsigned int depth = 0;
|
||||||
@ -334,7 +348,7 @@ oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
depth = data[offset + 3];
|
depth = data[offset + 3];
|
||||||
}
|
}
|
||||||
sample.depth = depth * FEET;
|
sample.depth = depth * FEET;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
// Temperature (°F)
|
// Temperature (°F)
|
||||||
unsigned int temperature = 0;
|
unsigned int temperature = 0;
|
||||||
@ -344,7 +358,7 @@ oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
temperature = data[offset + 6];
|
temperature = data[offset + 6];
|
||||||
}
|
}
|
||||||
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
|
|
||||||
// NDL / Deco
|
// NDL / Deco
|
||||||
if (parser->model != AERIS500AI) {
|
if (parser->model != AERIS500AI) {
|
||||||
@ -358,8 +372,7 @@ oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
sample.deco.depth = 0.0;
|
sample.deco.depth = 0.0;
|
||||||
}
|
}
|
||||||
sample.deco.time = decotime * 60;
|
sample.deco.time = decotime * 60;
|
||||||
sample.deco.tts = 0;
|
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += PAGESIZE / 2;
|
offset += PAGESIZE / 2;
|
||||||
|
|||||||
@ -36,7 +36,7 @@ dc_status_t
|
|||||||
oceans_s1_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
oceans_s1_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
oceans_s1_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
oceans_s1_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,6 +58,7 @@ struct oceans_s1_parser_t {
|
|||||||
unsigned int divetime;
|
unsigned int divetime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static dc_status_t oceans_s1_parser_set_data(dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t oceans_s1_parser_get_datetime(dc_parser_t *abstract, dc_datetime_t *datetime);
|
static dc_status_t oceans_s1_parser_get_datetime(dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||||
static dc_status_t oceans_s1_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
static dc_status_t oceans_s1_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||||
static dc_status_t oceans_s1_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
static dc_status_t oceans_s1_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||||
@ -65,6 +66,7 @@ static dc_status_t oceans_s1_parser_samples_foreach(dc_parser_t *abstract, dc_sa
|
|||||||
static const dc_parser_vtable_t oceans_s1_parser_vtable = {
|
static const dc_parser_vtable_t oceans_s1_parser_vtable = {
|
||||||
sizeof(oceans_s1_parser_t),
|
sizeof(oceans_s1_parser_t),
|
||||||
DC_FAMILY_OCEANS_S1,
|
DC_FAMILY_OCEANS_S1,
|
||||||
|
oceans_s1_parser_set_data, /* set_data */
|
||||||
NULL, /* set_clock */
|
NULL, /* set_clock */
|
||||||
NULL, /* set_atmospheric */
|
NULL, /* set_atmospheric */
|
||||||
NULL, /* set_density */
|
NULL, /* set_density */
|
||||||
@ -75,7 +77,7 @@ static const dc_parser_vtable_t oceans_s1_parser_vtable = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
oceans_s1_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
oceans_s1_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||||
{
|
{
|
||||||
oceans_s1_parser_t *parser = NULL;
|
oceans_s1_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -83,7 +85,7 @@ oceans_s1_parser_create (dc_parser_t **out, dc_context_t *context, const unsigne
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (oceans_s1_parser_t *) dc_parser_allocate (context, &oceans_s1_parser_vtable, data, size);
|
parser = (oceans_s1_parser_t *) dc_parser_allocate (context, &oceans_s1_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -103,6 +105,23 @@ oceans_s1_parser_create (dc_parser_t **out, dc_context_t *context, const unsigne
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
oceans_s1_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
oceans_s1_parser_t *parser = (oceans_s1_parser_t *) abstract;
|
||||||
|
|
||||||
|
// Reset the cache.
|
||||||
|
parser->cached = 0;
|
||||||
|
parser->timestamp = 0;
|
||||||
|
parser->number = 0;
|
||||||
|
parser->divemode = 0;
|
||||||
|
parser->oxygen = 0;
|
||||||
|
parser->maxdepth = 0;
|
||||||
|
parser->divetime = 0;
|
||||||
|
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
oceans_s1_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
oceans_s1_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -147,7 +166,6 @@ oceans_s1_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne
|
|||||||
*((unsigned int *) value) = parser->divemode == SCUBA;
|
*((unsigned int *) value) = parser->divemode == SCUBA;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
gasmix->usage = DC_USAGE_NONE;
|
|
||||||
gasmix->helium = 0.0;
|
gasmix->helium = 0.0;
|
||||||
gasmix->oxygen = parser->oxygen / 100.0;
|
gasmix->oxygen = parser->oxygen / 100.0;
|
||||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||||
@ -231,19 +249,19 @@ oceans_s1_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
|
|||||||
unsigned int nsamples = seconds / interval;
|
unsigned int nsamples = seconds / interval;
|
||||||
for (unsigned int i = 0; i < nsamples; ++i) {
|
for (unsigned int i = 0; i < nsamples; ++i) {
|
||||||
time += interval;
|
time += interval;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
sample.depth = 0;
|
sample.depth = 0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
time += interval;
|
time += interval;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
sample.depth = depth / 100.0;
|
sample.depth = depth / 100.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
} else if (strncmp(line, "enddive", 7) == 0) {
|
} else if (strncmp(line, "enddive", 7) == 0) {
|
||||||
if (sscanf(line, "enddive %u,%u", &maxdepth, &divetime) != 2) {
|
if (sscanf(line, "enddive %u,%u", &maxdepth, &divetime) != 2) {
|
||||||
ERROR (parser->base.context, "Failed to parse the line '%s'.", line);
|
ERROR (parser->base.context, "Failed to parse the line '%s'.", line);
|
||||||
@ -262,14 +280,14 @@ oceans_s1_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
|
|||||||
}
|
}
|
||||||
|
|
||||||
time += interval;
|
time += interval;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
sample.depth = depth / 100.0;
|
sample.depth = depth / 100.0;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
sample.temperature = temperature;
|
sample.temperature = temperature;
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
|
|
||||||
if (events & EVENT_DECO_STOP) {
|
if (events & EVENT_DECO_STOP) {
|
||||||
sample.deco.type = DC_DECO_DECOSTOP;
|
sample.deco.type = DC_DECO_DECOSTOP;
|
||||||
@ -280,8 +298,7 @@ oceans_s1_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
|
|||||||
}
|
}
|
||||||
sample.deco.depth = 0.0;
|
sample.deco.depth = 0.0;
|
||||||
sample.deco.time = 0;
|
sample.deco.time = 0;
|
||||||
sample.deco.tts = 0;
|
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -41,7 +41,7 @@ typedef struct dc_parser_vtable_t dc_parser_vtable_t;
|
|||||||
struct dc_parser_t {
|
struct dc_parser_t {
|
||||||
const dc_parser_vtable_t *vtable;
|
const dc_parser_vtable_t *vtable;
|
||||||
dc_context_t *context;
|
dc_context_t *context;
|
||||||
unsigned char *data;
|
const unsigned char *data;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -50,6 +50,8 @@ struct dc_parser_vtable_t {
|
|||||||
|
|
||||||
dc_family_t type;
|
dc_family_t type;
|
||||||
|
|
||||||
|
dc_status_t (*set_data) (dc_parser_t *parser, const unsigned char *data, unsigned int size);
|
||||||
|
|
||||||
dc_status_t (*set_clock) (dc_parser_t *parser, unsigned int devtime, dc_ticks_t systime);
|
dc_status_t (*set_clock) (dc_parser_t *parser, unsigned int devtime, dc_ticks_t systime);
|
||||||
|
|
||||||
dc_status_t (*set_atmospheric) (dc_parser_t *parser, double atmospheric);
|
dc_status_t (*set_atmospheric) (dc_parser_t *parser, double atmospheric);
|
||||||
@ -66,7 +68,7 @@ struct dc_parser_vtable_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
dc_parser_t *
|
dc_parser_t *
|
||||||
dc_parser_allocate (dc_context_t *context, const dc_parser_vtable_t *vtable, const unsigned char data[], size_t size);
|
dc_parser_allocate (dc_context_t *context, const dc_parser_vtable_t *vtable);
|
||||||
|
|
||||||
void
|
void
|
||||||
dc_parser_deallocate (dc_parser_t *parser);
|
dc_parser_deallocate (dc_parser_t *parser);
|
||||||
@ -82,7 +84,7 @@ typedef struct sample_statistics_t {
|
|||||||
#define SAMPLE_STATISTICS_INITIALIZER {0, 0.0}
|
#define SAMPLE_STATISTICS_INITIALIZER {0, 0.0}
|
||||||
|
|
||||||
void
|
void
|
||||||
sample_statistics_cb (dc_sample_type_t type, const dc_sample_value_t *value, void *userdata);
|
sample_statistics_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
163
src/parser.c
163
src/parser.c
@ -20,7 +20,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "suunto_d9.h"
|
#include "suunto_d9.h"
|
||||||
@ -73,7 +72,7 @@
|
|||||||
#define REACTPROWHITE 0x4354
|
#define REACTPROWHITE 0x4354
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, dc_family_t family, unsigned int model)
|
dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t family, unsigned int model, unsigned int devtime, dc_ticks_t systime)
|
||||||
{
|
{
|
||||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||||
dc_parser_t *parser = NULL;
|
dc_parser_t *parser = NULL;
|
||||||
@ -83,127 +82,126 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, const unsigned
|
|||||||
|
|
||||||
switch (family) {
|
switch (family) {
|
||||||
case DC_FAMILY_SUUNTO_SOLUTION:
|
case DC_FAMILY_SUUNTO_SOLUTION:
|
||||||
rc = suunto_solution_parser_create (&parser, context, data, size);
|
rc = suunto_solution_parser_create (&parser, context);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_SUUNTO_EON:
|
case DC_FAMILY_SUUNTO_EON:
|
||||||
rc = suunto_eon_parser_create (&parser, context, data, size, 0);
|
rc = suunto_eon_parser_create (&parser, context, 0);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_SUUNTO_VYPER:
|
case DC_FAMILY_SUUNTO_VYPER:
|
||||||
if (model == 0x01)
|
if (model == 0x01)
|
||||||
rc = suunto_eon_parser_create (&parser, context, data, size, 1);
|
rc = suunto_eon_parser_create (&parser, context, 1);
|
||||||
else
|
else
|
||||||
rc = suunto_vyper_parser_create (&parser, context, data, size);
|
rc = suunto_vyper_parser_create (&parser, context);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_SUUNTO_VYPER2:
|
case DC_FAMILY_SUUNTO_VYPER2:
|
||||||
case DC_FAMILY_SUUNTO_D9:
|
case DC_FAMILY_SUUNTO_D9:
|
||||||
rc = suunto_d9_parser_create (&parser, context, data, size, model);
|
rc = suunto_d9_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_SUUNTO_EONSTEEL:
|
case DC_FAMILY_SUUNTO_EONSTEEL:
|
||||||
rc = suunto_eonsteel_parser_create(&parser, context, data, size, model);
|
rc = suunto_eonsteel_parser_create(&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_UWATEC_ALADIN:
|
case DC_FAMILY_UWATEC_ALADIN:
|
||||||
case DC_FAMILY_UWATEC_MEMOMOUSE:
|
case DC_FAMILY_UWATEC_MEMOMOUSE:
|
||||||
rc = uwatec_memomouse_parser_create (&parser, context, data, size);
|
rc = uwatec_memomouse_parser_create (&parser, context, devtime, systime);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_UWATEC_SMART:
|
case DC_FAMILY_UWATEC_SMART:
|
||||||
rc = uwatec_smart_parser_create (&parser, context, data, size, model);
|
rc = uwatec_smart_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_REEFNET_SENSUS:
|
case DC_FAMILY_REEFNET_SENSUS:
|
||||||
rc = reefnet_sensus_parser_create (&parser, context, data, size);
|
rc = reefnet_sensus_parser_create (&parser, context, devtime, systime);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_REEFNET_SENSUSPRO:
|
case DC_FAMILY_REEFNET_SENSUSPRO:
|
||||||
rc = reefnet_sensuspro_parser_create (&parser, context, data, size);
|
rc = reefnet_sensuspro_parser_create (&parser, context, devtime, systime);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_REEFNET_SENSUSULTRA:
|
case DC_FAMILY_REEFNET_SENSUSULTRA:
|
||||||
rc = reefnet_sensusultra_parser_create (&parser, context, data, size);
|
rc = reefnet_sensusultra_parser_create (&parser, context, devtime, systime);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_OCEANIC_VTPRO:
|
case DC_FAMILY_OCEANIC_VTPRO:
|
||||||
rc = oceanic_vtpro_parser_create (&parser, context, data, size, model);
|
rc = oceanic_vtpro_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_OCEANIC_VEO250:
|
case DC_FAMILY_OCEANIC_VEO250:
|
||||||
rc = oceanic_veo250_parser_create (&parser, context, data, size, model);
|
rc = oceanic_veo250_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_OCEANIC_ATOM2:
|
case DC_FAMILY_OCEANIC_ATOM2:
|
||||||
case DC_FAMILY_PELAGIC_I330R:
|
|
||||||
if (model == REACTPROWHITE)
|
if (model == REACTPROWHITE)
|
||||||
rc = oceanic_veo250_parser_create (&parser, context, data, size, model);
|
rc = oceanic_veo250_parser_create (&parser, context, model);
|
||||||
else
|
else
|
||||||
rc = oceanic_atom2_parser_create (&parser, context, data, size, model);
|
rc = oceanic_atom2_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_MARES_NEMO:
|
case DC_FAMILY_MARES_NEMO:
|
||||||
case DC_FAMILY_MARES_PUCK:
|
case DC_FAMILY_MARES_PUCK:
|
||||||
rc = mares_nemo_parser_create (&parser, context, data, size, model);
|
rc = mares_nemo_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_MARES_DARWIN:
|
case DC_FAMILY_MARES_DARWIN:
|
||||||
rc = mares_darwin_parser_create (&parser, context, data, size, model);
|
rc = mares_darwin_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_MARES_ICONHD:
|
case DC_FAMILY_MARES_ICONHD:
|
||||||
rc = mares_iconhd_parser_create (&parser, context, data, size, model);
|
rc = mares_iconhd_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_HW_OSTC:
|
case DC_FAMILY_HW_OSTC:
|
||||||
rc = hw_ostc_parser_create (&parser, context, data, size);
|
rc = hw_ostc_parser_create (&parser, context);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_HW_FROG:
|
case DC_FAMILY_HW_FROG:
|
||||||
case DC_FAMILY_HW_OSTC3:
|
case DC_FAMILY_HW_OSTC3:
|
||||||
rc = hw_ostc3_parser_create (&parser, context, data, size, model);
|
rc = hw_ostc3_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_CRESSI_EDY:
|
case DC_FAMILY_CRESSI_EDY:
|
||||||
case DC_FAMILY_ZEAGLE_N2ITION3:
|
case DC_FAMILY_ZEAGLE_N2ITION3:
|
||||||
rc = cressi_edy_parser_create (&parser, context, data, size, model);
|
rc = cressi_edy_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_CRESSI_LEONARDO:
|
case DC_FAMILY_CRESSI_LEONARDO:
|
||||||
rc = cressi_leonardo_parser_create (&parser, context, data, size, model);
|
rc = cressi_leonardo_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_CRESSI_GOA:
|
case DC_FAMILY_CRESSI_GOA:
|
||||||
rc = cressi_goa_parser_create (&parser, context, data, size, model);
|
rc = cressi_goa_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_ATOMICS_COBALT:
|
case DC_FAMILY_ATOMICS_COBALT:
|
||||||
rc = atomics_cobalt_parser_create (&parser, context, data, size);
|
rc = atomics_cobalt_parser_create (&parser, context);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_SHEARWATER_PREDATOR:
|
case DC_FAMILY_SHEARWATER_PREDATOR:
|
||||||
rc = shearwater_predator_parser_create (&parser, context, data, size, model);
|
rc = shearwater_predator_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_SHEARWATER_PETREL:
|
case DC_FAMILY_SHEARWATER_PETREL:
|
||||||
rc = shearwater_petrel_parser_create (&parser, context, data, size, model);
|
rc = shearwater_petrel_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_DIVERITE_NITEKQ:
|
case DC_FAMILY_DIVERITE_NITEKQ:
|
||||||
rc = diverite_nitekq_parser_create (&parser, context, data, size);
|
rc = diverite_nitekq_parser_create (&parser, context);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_CITIZEN_AQUALAND:
|
case DC_FAMILY_CITIZEN_AQUALAND:
|
||||||
rc = citizen_aqualand_parser_create (&parser, context, data, size);
|
rc = citizen_aqualand_parser_create (&parser, context);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_DIVESYSTEM_IDIVE:
|
case DC_FAMILY_DIVESYSTEM_IDIVE:
|
||||||
rc = divesystem_idive_parser_create (&parser, context, data, size, model);
|
rc = divesystem_idive_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_COCHRAN_COMMANDER:
|
case DC_FAMILY_COCHRAN_COMMANDER:
|
||||||
rc = cochran_commander_parser_create (&parser, context, data, size, model);
|
rc = cochran_commander_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_TECDIVING_DIVECOMPUTEREU:
|
case DC_FAMILY_TECDIVING_DIVECOMPUTEREU:
|
||||||
rc = tecdiving_divecomputereu_parser_create (&parser, context, data, size);
|
rc = tecdiving_divecomputereu_parser_create (&parser, context);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_MCLEAN_EXTREME:
|
case DC_FAMILY_MCLEAN_EXTREME:
|
||||||
rc = mclean_extreme_parser_create (&parser, context, data, size);
|
rc = mclean_extreme_parser_create (&parser, context);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_LIQUIVISION_LYNX:
|
case DC_FAMILY_LIQUIVISION_LYNX:
|
||||||
rc = liquivision_lynx_parser_create (&parser, context, data, size, model);
|
rc = liquivision_lynx_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_SPORASUB_SP2:
|
case DC_FAMILY_SPORASUB_SP2:
|
||||||
rc = sporasub_sp2_parser_create (&parser, context, data, size);
|
rc = sporasub_sp2_parser_create (&parser, context);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_DEEPSIX_EXCURSION:
|
case DC_FAMILY_DEEPSIX_EXCURSION:
|
||||||
rc = deepsix_excursion_parser_create (&parser, context, data, size);
|
rc = deepsix_excursion_parser_create (&parser, context);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_SEAC_SCREEN:
|
case DC_FAMILY_SEAC_SCREEN:
|
||||||
rc = seac_screen_parser_create (&parser, context, data, size);
|
rc = seac_screen_parser_create (&parser, context);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_DEEPBLU_COSMIQ:
|
case DC_FAMILY_DEEPBLU_COSMIQ:
|
||||||
rc = deepblu_cosmiq_parser_create (&parser, context, data, size);
|
rc = deepblu_cosmiq_parser_create (&parser, context);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_OCEANS_S1:
|
case DC_FAMILY_OCEANS_S1:
|
||||||
rc = oceans_s1_parser_create (&parser, context, data, size);
|
rc = oceans_s1_parser_create (&parser, context);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_DIVESOFT_FREEDOM:
|
case DC_FAMILY_DIVESOFT_FREEDOM:
|
||||||
rc = divesoft_freedom_parser_create (&parser, context, data, size);
|
rc = divesoft_freedom_parser_create (&parser, context);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
@ -215,42 +213,26 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, const unsigned
|
|||||||
}
|
}
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
dc_parser_new (dc_parser_t **out, dc_device_t *device, const unsigned char data[], size_t size)
|
dc_parser_new (dc_parser_t **out, dc_device_t *device)
|
||||||
{
|
{
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
|
||||||
dc_parser_t *parser = NULL;
|
|
||||||
|
|
||||||
if (device == NULL)
|
if (device == NULL)
|
||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
status = dc_parser_new_internal (&parser, device->context, data, size,
|
return dc_parser_new_internal (out, device->context,
|
||||||
dc_device_get_type (device), device->devinfo.model);
|
dc_device_get_type (device), device->devinfo.model,
|
||||||
if (status != DC_STATUS_SUCCESS)
|
device->clock.devtime, device->clock.systime);
|
||||||
goto error_exit;
|
|
||||||
|
|
||||||
status = dc_parser_set_clock (parser, device->clock.devtime, device->clock.systime);
|
|
||||||
if (status != DC_STATUS_SUCCESS && status != DC_STATUS_UNSUPPORTED)
|
|
||||||
goto error_free;
|
|
||||||
|
|
||||||
*out = parser;
|
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
|
||||||
|
|
||||||
error_free:
|
|
||||||
dc_parser_deallocate (parser);
|
|
||||||
error_exit:
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
dc_parser_new2 (dc_parser_t **out, dc_context_t *context, dc_descriptor_t *descriptor, const unsigned char data[], size_t size)
|
dc_parser_new2 (dc_parser_t **out, dc_context_t *context, dc_descriptor_t *descriptor, unsigned int devtime, dc_ticks_t systime)
|
||||||
{
|
{
|
||||||
return dc_parser_new_internal (out, context, data, size,
|
return dc_parser_new_internal (out, context,
|
||||||
dc_descriptor_get_type (descriptor), dc_descriptor_get_model (descriptor));
|
dc_descriptor_get_type (descriptor), dc_descriptor_get_model (descriptor),
|
||||||
|
devtime, systime);
|
||||||
}
|
}
|
||||||
|
|
||||||
dc_parser_t *
|
dc_parser_t *
|
||||||
dc_parser_allocate (dc_context_t *context, const dc_parser_vtable_t *vtable, const unsigned char data[], size_t size)
|
dc_parser_allocate (dc_context_t *context, const dc_parser_vtable_t *vtable)
|
||||||
{
|
{
|
||||||
dc_parser_t *parser = NULL;
|
dc_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -267,34 +249,15 @@ dc_parser_allocate (dc_context_t *context, const dc_parser_vtable_t *vtable, con
|
|||||||
// Initialize the base class.
|
// Initialize the base class.
|
||||||
parser->vtable = vtable;
|
parser->vtable = vtable;
|
||||||
parser->context = context;
|
parser->context = context;
|
||||||
|
parser->data = NULL;
|
||||||
|
parser->size = 0;
|
||||||
|
|
||||||
if (size) {
|
|
||||||
// Allocate memory for the data.
|
|
||||||
parser->data = malloc (size);
|
|
||||||
if (parser->data == NULL) {
|
|
||||||
ERROR (context, "Failed to allocate memory.");
|
|
||||||
free (parser);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the data.
|
|
||||||
memcpy (parser->data, data, size);
|
|
||||||
parser->size = size;
|
|
||||||
} else {
|
|
||||||
parser->data = NULL;
|
|
||||||
parser->size = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
return parser;
|
return parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dc_parser_deallocate (dc_parser_t *parser)
|
dc_parser_deallocate (dc_parser_t *parser)
|
||||||
{
|
{
|
||||||
if (parser == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
free (parser->data);
|
|
||||||
free (parser);
|
free (parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,6 +320,22 @@ dc_parser_set_density (dc_parser_t *parser, double density)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dc_status_t
|
||||||
|
dc_parser_set_data (dc_parser_t *parser, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
if (parser == NULL)
|
||||||
|
return DC_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
|
if (parser->vtable->set_data == NULL)
|
||||||
|
return DC_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
|
parser->data = data;
|
||||||
|
parser->size = size;
|
||||||
|
|
||||||
|
return parser->vtable->set_data (parser, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
dc_parser_get_datetime (dc_parser_t *parser, dc_datetime_t *datetime)
|
dc_parser_get_datetime (dc_parser_t *parser, dc_datetime_t *datetime)
|
||||||
{
|
{
|
||||||
@ -414,17 +393,17 @@ dc_parser_destroy (dc_parser_t *parser)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
sample_statistics_cb (dc_sample_type_t type, const dc_sample_value_t *value, void *userdata)
|
sample_statistics_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata)
|
||||||
{
|
{
|
||||||
sample_statistics_t *statistics = (sample_statistics_t *) userdata;
|
sample_statistics_t *statistics = (sample_statistics_t *) userdata;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case DC_SAMPLE_TIME:
|
case DC_SAMPLE_TIME:
|
||||||
statistics->divetime = value->time / 1000;
|
statistics->divetime = value.time;
|
||||||
break;
|
break;
|
||||||
case DC_SAMPLE_DEPTH:
|
case DC_SAMPLE_DEPTH:
|
||||||
if (statistics->maxdepth < value->depth)
|
if (statistics->maxdepth < value.depth)
|
||||||
statistics->maxdepth = value->depth;
|
statistics->maxdepth = value.depth;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -1,646 +0,0 @@
|
|||||||
/*
|
|
||||||
* libdivecomputer
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023 Janice McLaughlin
|
|
||||||
*
|
|
||||||
* 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> // memcpy
|
|
||||||
#include <stdlib.h> // malloc, free
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include <libdivecomputer/ble.h>
|
|
||||||
|
|
||||||
#include "pelagic_i330r.h"
|
|
||||||
#include "oceanic_common.h"
|
|
||||||
|
|
||||||
#include "context-private.h"
|
|
||||||
#include "device-private.h"
|
|
||||||
#include "ringbuffer.h"
|
|
||||||
#include "rbstream.h"
|
|
||||||
#include "checksum.h"
|
|
||||||
#include "array.h"
|
|
||||||
|
|
||||||
#define UNDEFINED 0
|
|
||||||
|
|
||||||
#define STARTBYTE 0xCD
|
|
||||||
|
|
||||||
#define FLAG_NONE 0x00
|
|
||||||
#define FLAG_REQUEST 0x40
|
|
||||||
#define FLAG_DATA 0x80
|
|
||||||
#define FLAG_LAST 0xC0
|
|
||||||
|
|
||||||
#define CMD_ACCESS_REQUEST 0xFA
|
|
||||||
#define CMD_ACCESS_CODE 0xFB
|
|
||||||
#define CMD_AUTHENTICATION 0x97
|
|
||||||
#define CMD_WAKEUP_RDONLY 0x21
|
|
||||||
#define CMD_WAKEUP_RDWR 0x22
|
|
||||||
#define CMD_READ_HW_CAL 0x27
|
|
||||||
#define CMD_READ_A2D 0x25
|
|
||||||
#define CMD_READ_DEVICE_REC 0x31
|
|
||||||
#define CMD_READ_GEN_SET 0x29
|
|
||||||
#define CMD_READ_EXFLASHMAP 0x2F
|
|
||||||
#define CMD_READ_FLASH 0x0D
|
|
||||||
|
|
||||||
#define RSP_READY 1
|
|
||||||
#define RSP_DONE 2
|
|
||||||
|
|
||||||
#define MAXPACKET 255
|
|
||||||
|
|
||||||
#define MAXPASSCODE 6
|
|
||||||
|
|
||||||
typedef struct pelagic_i330r_device_t {
|
|
||||||
oceanic_common_device_t base;
|
|
||||||
dc_iostream_t *iostream;
|
|
||||||
unsigned char accesscode[16];
|
|
||||||
unsigned char id[16];
|
|
||||||
unsigned char hwcal[256];
|
|
||||||
unsigned char flashmap[256];
|
|
||||||
unsigned int model;
|
|
||||||
} pelagic_i330r_device_t;
|
|
||||||
|
|
||||||
static dc_status_t pelagic_i330r_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size);
|
|
||||||
static dc_status_t pelagic_i330r_device_devinfo (dc_device_t *abstract, dc_event_progress_t *progress);
|
|
||||||
static dc_status_t pelagic_i330r_device_pointers (dc_device_t *abstract, dc_event_progress_t *progress, unsigned int *rb_logbook_begin, unsigned int *rb_logbook_end, unsigned int *rb_profile_begin, unsigned int *rb_profile_end);
|
|
||||||
|
|
||||||
static const oceanic_common_device_vtable_t pelagic_i330r_device_vtable = {
|
|
||||||
{
|
|
||||||
sizeof(pelagic_i330r_device_t),
|
|
||||||
DC_FAMILY_PELAGIC_I330R,
|
|
||||||
oceanic_common_device_set_fingerprint, /* set_fingerprint */
|
|
||||||
pelagic_i330r_device_read, /* read */
|
|
||||||
NULL, /* write */
|
|
||||||
oceanic_common_device_dump, /* dump */
|
|
||||||
oceanic_common_device_foreach, /* foreach */
|
|
||||||
NULL, /* timesync */
|
|
||||||
NULL /* close */
|
|
||||||
},
|
|
||||||
pelagic_i330r_device_devinfo,
|
|
||||||
pelagic_i330r_device_pointers,
|
|
||||||
oceanic_common_device_logbook,
|
|
||||||
oceanic_common_device_profile,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const oceanic_common_layout_t pelagic_i330r = {
|
|
||||||
0x00400000, /* memsize */
|
|
||||||
0, /* highmem */
|
|
||||||
UNDEFINED, /* cf_devinfo */
|
|
||||||
UNDEFINED, /* cf_pointers */
|
|
||||||
0x00102000, /* rb_logbook_begin */
|
|
||||||
0x00106000, /* rb_logbook_end */
|
|
||||||
64, /* rb_logbook_entry_size */
|
|
||||||
0, /* rb_logbook_direction */
|
|
||||||
0x0010A000, /* rb_profile_begin */
|
|
||||||
0x00400000, /* rb_profile_end */
|
|
||||||
1, /* pt_mode_global */
|
|
||||||
4, /* pt_mode_logbook */
|
|
||||||
UNDEFINED, /* pt_mode_serial */
|
|
||||||
};
|
|
||||||
|
|
||||||
static const oceanic_common_layout_t pelagic_dsx = {
|
|
||||||
0x02000000, /* memsize */
|
|
||||||
0, /* highmem */
|
|
||||||
UNDEFINED, /* cf_devinfo */
|
|
||||||
UNDEFINED, /* cf_pointers */
|
|
||||||
0x00800000, /* rb_logbook_begin */
|
|
||||||
0x00880000, /* rb_logbook_end */
|
|
||||||
512, /* rb_logbook_entry_size */
|
|
||||||
1, /* rb_logbook_direction */
|
|
||||||
0x01000000, /* rb_profile_begin */
|
|
||||||
0x02000000, /* rb_profile_end */
|
|
||||||
1, /* pt_mode_global */
|
|
||||||
4, /* pt_mode_logbook */
|
|
||||||
UNDEFINED /* pt_mode_serial */
|
|
||||||
};
|
|
||||||
|
|
||||||
static unsigned char
|
|
||||||
checksum (const unsigned char data[], unsigned int size)
|
|
||||||
{
|
|
||||||
unsigned int csum = 0;
|
|
||||||
for (unsigned int i = 0; i < size; i++) {
|
|
||||||
unsigned int a = csum ^ data[i];
|
|
||||||
unsigned int b = (a >> 7) ^ ((a >> 4) ^ a);
|
|
||||||
csum = ((b << 4) & 0xFF) ^ ((b << 1) & 0xFF);
|
|
||||||
}
|
|
||||||
return csum & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
pelagic_i330r_send (pelagic_i330r_device_t *device, unsigned char cmd, unsigned char flag, const unsigned char data[], unsigned int size)
|
|
||||||
{
|
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
|
||||||
dc_device_t *abstract = (dc_device_t *) device;
|
|
||||||
|
|
||||||
if (size > MAXPACKET) {
|
|
||||||
ERROR (abstract->context, "Packet payload is too large (%u).", size);
|
|
||||||
return DC_STATUS_INVALIDARGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char packet[MAXPACKET + 5] = {
|
|
||||||
STARTBYTE,
|
|
||||||
flag,
|
|
||||||
cmd,
|
|
||||||
0,
|
|
||||||
size
|
|
||||||
};
|
|
||||||
if (size) {
|
|
||||||
memcpy(packet + 5, data, size);
|
|
||||||
}
|
|
||||||
packet[3] = checksum (packet, size + 5);
|
|
||||||
|
|
||||||
// Send the data packet.
|
|
||||||
status = dc_iostream_write (device->iostream, packet, size + 5, NULL);
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to send the command.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
pelagic_i330r_recv (pelagic_i330r_device_t *device, unsigned char cmd, unsigned char data[], unsigned int size, unsigned int *errorcode)
|
|
||||||
{
|
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
|
||||||
dc_device_t *abstract = (dc_device_t *) device;
|
|
||||||
unsigned char packet[MAXPACKET + 5] = {0};
|
|
||||||
unsigned int errcode = 0;
|
|
||||||
|
|
||||||
unsigned int nbytes = 0;
|
|
||||||
while (1) {
|
|
||||||
// Read the data packet.
|
|
||||||
size_t transferred = 0;
|
|
||||||
status = dc_iostream_read (device->iostream, packet, sizeof(packet), &transferred);
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to receive the data packet.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the minimum packet size.
|
|
||||||
if (transferred < 5) {
|
|
||||||
ERROR (abstract->context, "Invalid packet length (" DC_PRINTF_SIZE ").", transferred);
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the start byte.
|
|
||||||
if (packet[0] != STARTBYTE) {
|
|
||||||
ERROR (abstract->context, "Unexpected packet start byte (%02x).", packet[0]);
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the command byte.
|
|
||||||
if (packet[2] != cmd) {
|
|
||||||
ERROR (abstract->context, "Unexpected packet command byte (%02x).", packet[2]);
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the length byte.
|
|
||||||
unsigned int length = packet[4];
|
|
||||||
if (length + 5 > transferred) {
|
|
||||||
ERROR (abstract->context, "Invalid packet length (%u).", length);
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the checksum.
|
|
||||||
unsigned char crc = packet[3]; packet[3] = 0;
|
|
||||||
unsigned char ccrc = checksum (packet, length + 5);
|
|
||||||
if (crc != ccrc) {
|
|
||||||
ERROR (abstract->context, "Unexpected packet checksum (%02x %02x).", crc, ccrc);
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the flag byte for the last packet.
|
|
||||||
unsigned char flag = packet[1];
|
|
||||||
if ((flag & FLAG_LAST) == FLAG_LAST) {
|
|
||||||
// The last packet (typically 2 bytes) does not get appended!
|
|
||||||
if (length) {
|
|
||||||
errcode = packet[5];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append the payload data to the output buffer. If the output
|
|
||||||
// buffer is too small, the error is not reported immediately
|
|
||||||
// but delayed until all packets have been received.
|
|
||||||
if (nbytes < size) {
|
|
||||||
unsigned int n = length;
|
|
||||||
if (nbytes + n > size) {
|
|
||||||
n = size - nbytes;
|
|
||||||
}
|
|
||||||
memcpy (data + nbytes, packet + 5, n);
|
|
||||||
}
|
|
||||||
nbytes += length;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the expected number of bytes.
|
|
||||||
if (nbytes != size) {
|
|
||||||
ERROR (abstract->context, "Unexpected number of bytes received (%u %u).", nbytes, size);
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errorcode) {
|
|
||||||
*errorcode = errcode;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
pelagic_i330r_transfer (pelagic_i330r_device_t *device, unsigned char cmd, unsigned char flag, const unsigned char data[], unsigned int size, unsigned char answer[], unsigned int asize, unsigned int response)
|
|
||||||
{
|
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
|
||||||
dc_device_t *abstract = (dc_device_t *) device;
|
|
||||||
unsigned int errorcode = 0;
|
|
||||||
|
|
||||||
status = pelagic_i330r_send (device, cmd, flag, data, size);
|
|
||||||
if (status != DC_STATUS_SUCCESS)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
status = pelagic_i330r_recv (device, cmd, answer, asize, &errorcode);
|
|
||||||
if (status != DC_STATUS_SUCCESS)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
if (errorcode != response) {
|
|
||||||
ERROR (abstract->context, "Unexpected response code (%u)", errorcode);
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
pelagic_i330r_init_accesscode (pelagic_i330r_device_t *device)
|
|
||||||
{
|
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
|
||||||
|
|
||||||
const unsigned char zero[9] = {0};
|
|
||||||
status = pelagic_i330r_transfer (device, CMD_ACCESS_REQUEST, FLAG_REQUEST, zero, sizeof(zero), NULL, 0, RSP_READY);
|
|
||||||
if (status != DC_STATUS_SUCCESS)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
status = pelagic_i330r_transfer (device, CMD_ACCESS_REQUEST, FLAG_DATA, device->accesscode, sizeof(device->accesscode), NULL, 0, RSP_DONE);
|
|
||||||
if (status != DC_STATUS_SUCCESS)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
pelagic_i330r_init_passcode (pelagic_i330r_device_t *device, const char *pincode)
|
|
||||||
{
|
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
|
||||||
dc_device_t *abstract = (dc_device_t *) device;
|
|
||||||
unsigned char passcode[MAXPASSCODE] = {0};
|
|
||||||
|
|
||||||
// Check the maximum length.
|
|
||||||
size_t len = pincode ? strlen (pincode) : 0;
|
|
||||||
if (len > sizeof(passcode)) {
|
|
||||||
ERROR (abstract->context, "Invalid pincode length (" DC_PRINTF_SIZE ").", len);
|
|
||||||
return DC_STATUS_INVALIDARGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert to binary number.
|
|
||||||
unsigned int offset = sizeof(passcode) - len;
|
|
||||||
for (unsigned int i = 0; i < len; i++) {
|
|
||||||
unsigned char c = pincode[i];
|
|
||||||
if (c < '0' || c > '9') {
|
|
||||||
ERROR (abstract->context, "Invalid pincode character (%c).", c);
|
|
||||||
return DC_STATUS_INVALIDARGS;
|
|
||||||
}
|
|
||||||
passcode[offset + i] = c - '0';
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned char zero[9] = {0};
|
|
||||||
status = pelagic_i330r_transfer (device, CMD_ACCESS_CODE, FLAG_REQUEST, zero, sizeof(zero), NULL, 0, RSP_READY);
|
|
||||||
if (status != DC_STATUS_SUCCESS)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
status = pelagic_i330r_transfer (device, CMD_ACCESS_CODE, FLAG_DATA, passcode, sizeof(passcode), device->accesscode, sizeof(device->accesscode), RSP_DONE);
|
|
||||||
if (status != DC_STATUS_SUCCESS)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
HEXDUMP (abstract->context, DC_LOGLEVEL_DEBUG, "Access code", device->accesscode, sizeof(device->accesscode));
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
pelagic_i330r_init_handshake (pelagic_i330r_device_t *device, unsigned int readwrite)
|
|
||||||
{
|
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
|
||||||
dc_device_t *abstract = (dc_device_t *) device;
|
|
||||||
|
|
||||||
const unsigned char cmd = readwrite ? CMD_WAKEUP_RDWR : CMD_WAKEUP_RDONLY;
|
|
||||||
|
|
||||||
const unsigned char args[9] = {0, 0, 0, 0, 0x0C, 0, 0, 0, 0};
|
|
||||||
status = pelagic_i330r_transfer (device, cmd, FLAG_REQUEST, args, sizeof(args), device->id, sizeof(device->id), RSP_DONE);
|
|
||||||
if (status != DC_STATUS_SUCCESS)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
HEXDUMP (abstract->context, DC_LOGLEVEL_DEBUG, "ID", device->id, sizeof(device->id));
|
|
||||||
|
|
||||||
device->model = array_uint16_be (device->id + 12);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
pelagic_i330r_init_auth (pelagic_i330r_device_t *device)
|
|
||||||
{
|
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
|
||||||
|
|
||||||
const unsigned char args[2][9] = {
|
|
||||||
{0xFF, 0xFF, 0xFF, 0xFF}, // DSX
|
|
||||||
{0x37, 0x30, 0x31, 0x55}, // I330R
|
|
||||||
};
|
|
||||||
unsigned int args_idx = device->model == DSX ? 0 : 1;
|
|
||||||
status = pelagic_i330r_transfer (device, CMD_AUTHENTICATION, FLAG_REQUEST, args[args_idx], sizeof(args[args_idx]), NULL, 0, RSP_READY);
|
|
||||||
if (status != DC_STATUS_SUCCESS)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
pelagic_i330r_init (pelagic_i330r_device_t *device)
|
|
||||||
{
|
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
|
||||||
dc_device_t *abstract = (dc_device_t *) device;
|
|
||||||
|
|
||||||
// Get the bluetooth access code.
|
|
||||||
status = dc_iostream_ioctl (device->iostream, DC_IOCTL_BLE_GET_ACCESSCODE, device->accesscode, sizeof(device->accesscode));
|
|
||||||
if (status != DC_STATUS_SUCCESS && status != DC_STATUS_UNSUPPORTED) {
|
|
||||||
ERROR (abstract->context, "Failed to get the access code.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (array_isequal (device->accesscode, sizeof(device->accesscode), 0)) {
|
|
||||||
// Request to display the PIN code.
|
|
||||||
status = pelagic_i330r_init_accesscode (device);
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to display the PIN code.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the bluetooth PIN code.
|
|
||||||
char pincode[6 + 1] = {0};
|
|
||||||
status = dc_iostream_ioctl (device->iostream, DC_IOCTL_BLE_GET_PINCODE, pincode, sizeof(pincode));
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to get the PIN code.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Force a null terminated string.
|
|
||||||
pincode[sizeof(pincode) - 1] = 0;
|
|
||||||
|
|
||||||
// Request the access code.
|
|
||||||
status = pelagic_i330r_init_passcode (device, pincode);
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to request the access code.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the bluetooth access code.
|
|
||||||
status = dc_iostream_ioctl (device->iostream, DC_IOCTL_BLE_SET_ACCESSCODE, device->accesscode, sizeof(device->accesscode));
|
|
||||||
if (status != DC_STATUS_SUCCESS && status != DC_STATUS_UNSUPPORTED) {
|
|
||||||
ERROR (abstract->context, "Failed to store the access code.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request access.
|
|
||||||
status = pelagic_i330r_init_accesscode (device);
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to request access.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the wakeup command.
|
|
||||||
status = pelagic_i330r_init_handshake (device, 1);
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to send the wakeup command.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the authentication code.
|
|
||||||
status = pelagic_i330r_init_auth (device);
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (abstract->context, "Failed to send the authentication code.");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
pelagic_i330r_download (pelagic_i330r_device_t *device, unsigned char cmd, const unsigned char data[], unsigned int size, unsigned char answer[], unsigned int asize)
|
|
||||||
{
|
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
|
||||||
dc_device_t *abstract = (dc_device_t *) device;
|
|
||||||
|
|
||||||
status = pelagic_i330r_transfer (device, cmd, FLAG_REQUEST, data, size, answer, asize, RSP_DONE);
|
|
||||||
if (status != DC_STATUS_SUCCESS)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
// Verify the checksum
|
|
||||||
unsigned short crc = array_uint16_be (answer + asize - 2);
|
|
||||||
unsigned short ccrc = checksum_crc16_ccitt (answer, asize - 2, 0xffff, 0x0000);
|
|
||||||
if (crc != ccrc) {
|
|
||||||
ERROR (abstract->context, "Unexpected data checksum (%04x %04x).", crc, ccrc);
|
|
||||||
return DC_STATUS_PROTOCOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
dc_status_t
|
|
||||||
pelagic_i330r_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t *iostream, unsigned int model)
|
|
||||||
{
|
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
|
||||||
pelagic_i330r_device_t *device = NULL;
|
|
||||||
|
|
||||||
if (out == NULL)
|
|
||||||
return DC_STATUS_INVALIDARGS;
|
|
||||||
|
|
||||||
// Allocate memory.
|
|
||||||
device = (pelagic_i330r_device_t *) dc_device_allocate (context, &pelagic_i330r_device_vtable.base);
|
|
||||||
if (device == NULL) {
|
|
||||||
ERROR (context, "Failed to allocate memory.");
|
|
||||||
return DC_STATUS_NOMEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the base class.
|
|
||||||
oceanic_common_device_init (&device->base);
|
|
||||||
|
|
||||||
// Override the base class values.
|
|
||||||
device->base.multipage = 256;
|
|
||||||
|
|
||||||
// Set the default values.
|
|
||||||
device->iostream = iostream;
|
|
||||||
memset (device->accesscode, 0, sizeof(device->accesscode));
|
|
||||||
memset (device->id, 0, sizeof(device->id));
|
|
||||||
memset (device->hwcal, 0, sizeof(device->hwcal));
|
|
||||||
memset (device->flashmap, 0, sizeof(device->flashmap));
|
|
||||||
device->model = 0;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform the bluetooth authentication.
|
|
||||||
status = pelagic_i330r_init (device);
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (context, "Failed to perform the bluetooth authentication.");
|
|
||||||
goto error_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Download the calibration data.
|
|
||||||
const unsigned char args[9] = {0, 0, 0, 0, 0, 0x01, 0, 0, 0};
|
|
||||||
status = pelagic_i330r_download (device, CMD_READ_HW_CAL, args, sizeof(args), device->hwcal, sizeof(device->hwcal));
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (context, "Failed to download the calibration data.");
|
|
||||||
goto error_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
HEXDUMP (context, DC_LOGLEVEL_DEBUG, "Hwcal", device->hwcal, sizeof(device->hwcal));
|
|
||||||
|
|
||||||
// Download the flash map.
|
|
||||||
const unsigned char zero[9] = {0};
|
|
||||||
status = pelagic_i330r_download (device, CMD_READ_EXFLASHMAP, zero, sizeof(zero), device->flashmap, sizeof(device->flashmap));
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
ERROR (context, "Failed to download the flash map.");
|
|
||||||
goto error_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
HEXDUMP (context, DC_LOGLEVEL_DEBUG, "Flashmap", device->flashmap, sizeof(device->flashmap));
|
|
||||||
|
|
||||||
// Detect the memory layout.
|
|
||||||
if (device->model == DSX) {
|
|
||||||
device->base.layout = &pelagic_dsx;
|
|
||||||
} else {
|
|
||||||
device->base.layout = &pelagic_i330r;
|
|
||||||
}
|
|
||||||
|
|
||||||
*out = (dc_device_t *) device;
|
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
|
||||||
|
|
||||||
error_free:
|
|
||||||
dc_device_deallocate ((dc_device_t *) device);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
pelagic_i330r_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size)
|
|
||||||
{
|
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
|
||||||
pelagic_i330r_device_t *device = (pelagic_i330r_device_t*) abstract;
|
|
||||||
|
|
||||||
unsigned char command[9] = {0};
|
|
||||||
array_uint32_le_set(command + 0, address);
|
|
||||||
array_uint32_le_set(command + 4, size);
|
|
||||||
|
|
||||||
status = pelagic_i330r_transfer (device, CMD_READ_FLASH, FLAG_NONE, command, sizeof(command), data, size, RSP_DONE);
|
|
||||||
if (status != DC_STATUS_SUCCESS) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
pelagic_i330r_device_devinfo (dc_device_t *abstract, dc_event_progress_t *progress)
|
|
||||||
{
|
|
||||||
pelagic_i330r_device_t *device = (pelagic_i330r_device_t *) abstract;
|
|
||||||
|
|
||||||
assert (device != NULL);
|
|
||||||
|
|
||||||
// Emit a device info event.
|
|
||||||
dc_event_devinfo_t devinfo;
|
|
||||||
devinfo.model = device->model;
|
|
||||||
devinfo.firmware = 0;
|
|
||||||
devinfo.serial =
|
|
||||||
bcd2dec (device->hwcal[12]) +
|
|
||||||
bcd2dec (device->hwcal[13]) * 100 +
|
|
||||||
bcd2dec (device->hwcal[14]) * 10000;
|
|
||||||
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);
|
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dc_status_t
|
|
||||||
pelagic_i330r_device_pointers (dc_device_t *abstract, dc_event_progress_t *progress, unsigned int *rb_logbook_begin, unsigned int *rb_logbook_end, unsigned int *rb_profile_begin, unsigned int *rb_profile_end)
|
|
||||||
{
|
|
||||||
pelagic_i330r_device_t *device = (pelagic_i330r_device_t *) abstract;
|
|
||||||
|
|
||||||
assert (device != NULL);
|
|
||||||
assert (device->base.layout != NULL);
|
|
||||||
assert (rb_logbook_begin != NULL && rb_logbook_end != NULL);
|
|
||||||
assert (rb_profile_begin != NULL && rb_profile_end != NULL);
|
|
||||||
|
|
||||||
const oceanic_common_layout_t *layout = device->base.layout;
|
|
||||||
|
|
||||||
// Get the logbook pointers.
|
|
||||||
unsigned int rb_logbook_min = array_uint32_le (device->flashmap + 0x50);
|
|
||||||
unsigned int rb_logbook_max = array_uint32_le (device->flashmap + 0x54);
|
|
||||||
unsigned int rb_logbook_first = array_uint32_le (device->flashmap + 0x58);
|
|
||||||
unsigned int rb_logbook_last = array_uint32_le (device->flashmap + 0x5C);
|
|
||||||
if (rb_logbook_min != 0 && rb_logbook_max != 0) {
|
|
||||||
rb_logbook_max += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the profile pointers.
|
|
||||||
unsigned int rb_profile_min = array_uint32_le (device->flashmap + 0x70);
|
|
||||||
unsigned int rb_profile_max = array_uint32_le (device->flashmap + 0x74);
|
|
||||||
unsigned int rb_profile_first = array_uint32_le (device->flashmap + 0x78);
|
|
||||||
unsigned int rb_profile_last = array_uint32_le (device->flashmap + 0x7C);
|
|
||||||
if (rb_profile_min != 0 && rb_profile_max != 0) {
|
|
||||||
rb_profile_max += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the logbook ringbuffer area.
|
|
||||||
if (rb_logbook_min != layout->rb_logbook_begin ||
|
|
||||||
rb_logbook_max != layout->rb_logbook_end) {
|
|
||||||
ERROR (abstract->context, "Unexpected logbook ringbuffer area (%08x %08x)",
|
|
||||||
rb_logbook_min, rb_logbook_max);
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the profile ringbuffer area.
|
|
||||||
if (rb_profile_min != layout->rb_profile_begin ||
|
|
||||||
rb_profile_max != layout->rb_profile_end) {
|
|
||||||
ERROR (abstract->context, "Unexpected profile ringbuffer area (%08x %08x)",
|
|
||||||
rb_profile_min, rb_profile_max);
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the begin/end pointers.
|
|
||||||
if (device->model == DSX) {
|
|
||||||
*rb_logbook_begin = rb_logbook_first;
|
|
||||||
*rb_logbook_end = rb_logbook_last;
|
|
||||||
} else {
|
|
||||||
*rb_logbook_begin = rb_logbook_min;
|
|
||||||
*rb_logbook_end = rb_logbook_last + 1;
|
|
||||||
}
|
|
||||||
*rb_profile_begin = rb_profile_first;
|
|
||||||
*rb_profile_end = rb_profile_last;
|
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
135
src/rbstream.c
135
src/rbstream.c
@ -28,13 +28,11 @@
|
|||||||
|
|
||||||
struct dc_rbstream_t {
|
struct dc_rbstream_t {
|
||||||
dc_device_t *device;
|
dc_device_t *device;
|
||||||
dc_rbstream_direction_t direction;
|
|
||||||
unsigned int pagesize;
|
unsigned int pagesize;
|
||||||
unsigned int packetsize;
|
unsigned int packetsize;
|
||||||
unsigned int begin;
|
unsigned int begin;
|
||||||
unsigned int end;
|
unsigned int end;
|
||||||
unsigned int address;
|
unsigned int address;
|
||||||
unsigned int offset;
|
|
||||||
unsigned int available;
|
unsigned int available;
|
||||||
unsigned int skip;
|
unsigned int skip;
|
||||||
unsigned char cache[];
|
unsigned char cache[];
|
||||||
@ -55,7 +53,7 @@ iceil (unsigned int x, unsigned int n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
dc_rbstream_new (dc_rbstream_t **out, dc_device_t *device, unsigned int pagesize, unsigned int packetsize, unsigned int begin, unsigned int end, unsigned int address, dc_rbstream_direction_t direction)
|
dc_rbstream_new (dc_rbstream_t **out, dc_device_t *device, unsigned int pagesize, unsigned int packetsize, unsigned int begin, unsigned int end, unsigned int address)
|
||||||
{
|
{
|
||||||
dc_rbstream_t *rbstream = NULL;
|
dc_rbstream_t *rbstream = NULL;
|
||||||
|
|
||||||
@ -80,18 +78,6 @@ dc_rbstream_new (dc_rbstream_t **out, dc_device_t *device, unsigned int pagesize
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ringbuffer boundaries should not be reversed.
|
|
||||||
if (begin > end) {
|
|
||||||
ERROR (device->context, "Ringbuffer boundaries reversed!");
|
|
||||||
return DC_STATUS_INVALIDARGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Packet size should be smaller than the ringbuffer size.
|
|
||||||
if (packetsize > (end - begin)) {
|
|
||||||
ERROR (device->context, "Packet size larger than the ringbuffer size!");
|
|
||||||
return DC_STATUS_INVALIDARGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Address should be inside the ringbuffer.
|
// Address should be inside the ringbuffer.
|
||||||
if (address < begin || address > end) {
|
if (address < begin || address > end) {
|
||||||
ERROR (device->context, "Address outside the ringbuffer!");
|
ERROR (device->context, "Address outside the ringbuffer!");
|
||||||
@ -106,64 +92,64 @@ dc_rbstream_new (dc_rbstream_t **out, dc_device_t *device, unsigned int pagesize
|
|||||||
}
|
}
|
||||||
|
|
||||||
rbstream->device = device;
|
rbstream->device = device;
|
||||||
rbstream->direction = direction;
|
|
||||||
rbstream->pagesize = pagesize;
|
rbstream->pagesize = pagesize;
|
||||||
rbstream->packetsize = packetsize;
|
rbstream->packetsize = packetsize;
|
||||||
rbstream->begin = begin;
|
rbstream->begin = begin;
|
||||||
rbstream->end = end;
|
rbstream->end = end;
|
||||||
if (direction == DC_RBSTREAM_FORWARD) {
|
rbstream->address = iceil(address, pagesize);
|
||||||
rbstream->address = ifloor(address, pagesize);
|
|
||||||
rbstream->skip = address - rbstream->address;
|
|
||||||
} else {
|
|
||||||
rbstream->address = iceil(address, pagesize);
|
|
||||||
rbstream->skip = rbstream->address - address;
|
|
||||||
}
|
|
||||||
rbstream->offset = 0;
|
|
||||||
rbstream->available = 0;
|
rbstream->available = 0;
|
||||||
|
rbstream->skip = rbstream->address - address;
|
||||||
|
|
||||||
*out = rbstream;
|
*out = rbstream;
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static dc_status_t
|
dc_status_t
|
||||||
dc_rbstream_read_backward (dc_rbstream_t *rbstream, dc_event_progress_t *progress, unsigned char data[], unsigned int size)
|
dc_rbstream_read (dc_rbstream_t *rbstream, dc_event_progress_t *progress, unsigned char data[], unsigned int size)
|
||||||
{
|
{
|
||||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if (rbstream == NULL)
|
||||||
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
|
unsigned int address = rbstream->address;
|
||||||
|
unsigned int available = rbstream->available;
|
||||||
|
unsigned int skip = rbstream->skip;
|
||||||
|
|
||||||
unsigned int nbytes = 0;
|
unsigned int nbytes = 0;
|
||||||
unsigned int offset = size;
|
unsigned int offset = size;
|
||||||
while (nbytes < size) {
|
while (nbytes < size) {
|
||||||
if (rbstream->available == 0) {
|
if (available == 0) {
|
||||||
// Handle the ringbuffer wrap point.
|
// Handle the ringbuffer wrap point.
|
||||||
if (rbstream->address == rbstream->begin)
|
if (address == rbstream->begin)
|
||||||
rbstream->address = rbstream->end;
|
address = rbstream->end;
|
||||||
|
|
||||||
// Calculate the packet size.
|
// Calculate the packet size.
|
||||||
unsigned int len = rbstream->packetsize;
|
unsigned int len = rbstream->packetsize;
|
||||||
if (rbstream->begin + len > rbstream->address)
|
if (rbstream->begin + len > address)
|
||||||
len = rbstream->address - rbstream->begin;
|
len = address - rbstream->begin;
|
||||||
|
|
||||||
|
// Move to the begin of the current packet.
|
||||||
|
address -= len;
|
||||||
|
|
||||||
// Read the packet into the cache.
|
// Read the packet into the cache.
|
||||||
rc = dc_device_read (rbstream->device, rbstream->address - len, rbstream->cache, rbstream->packetsize);
|
rc = dc_device_read (rbstream->device, address, rbstream->cache, rbstream->packetsize);
|
||||||
if (rc != DC_STATUS_SUCCESS)
|
if (rc != DC_STATUS_SUCCESS)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
// Move to the end of the next packet.
|
available = len - skip;
|
||||||
rbstream->address -= len;
|
skip = 0;
|
||||||
|
|
||||||
rbstream->available = len - rbstream->skip;
|
|
||||||
rbstream->skip = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int length = rbstream->available;
|
unsigned int length = available;
|
||||||
if (nbytes + length > size)
|
if (nbytes + length > size)
|
||||||
length = size - nbytes;
|
length = size - nbytes;
|
||||||
|
|
||||||
offset -= length;
|
offset -= length;
|
||||||
rbstream->available -= length;
|
available -= length;
|
||||||
|
|
||||||
memcpy (data + offset, rbstream->cache + rbstream->available, length);
|
memcpy (data + offset, rbstream->cache + available, length);
|
||||||
|
|
||||||
// Update and emit a progress event.
|
// Update and emit a progress event.
|
||||||
if (progress) {
|
if (progress) {
|
||||||
@ -174,76 +160,13 @@ dc_rbstream_read_backward (dc_rbstream_t *rbstream, dc_event_progress_t *progres
|
|||||||
nbytes += length;
|
nbytes += length;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
rbstream->address = address;
|
||||||
}
|
rbstream->available = available;
|
||||||
|
rbstream->skip = skip;
|
||||||
static dc_status_t
|
|
||||||
dc_rbstream_read_forward (dc_rbstream_t *rbstream, dc_event_progress_t *progress, unsigned char data[], unsigned int size)
|
|
||||||
{
|
|
||||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
|
||||||
|
|
||||||
unsigned int nbytes = 0;
|
|
||||||
while (nbytes < size) {
|
|
||||||
if (rbstream->available == 0) {
|
|
||||||
// Handle the ringbuffer wrap point.
|
|
||||||
if (rbstream->address == rbstream->end)
|
|
||||||
rbstream->address = rbstream->begin;
|
|
||||||
|
|
||||||
// Calculate the packet size.
|
|
||||||
unsigned int len = rbstream->packetsize;
|
|
||||||
if (rbstream->address + len > rbstream->end)
|
|
||||||
len = rbstream->end - rbstream->address;
|
|
||||||
|
|
||||||
// Calculate the excess number of bytes.
|
|
||||||
unsigned int extra = rbstream->packetsize - len;
|
|
||||||
|
|
||||||
// Read the packet into the cache.
|
|
||||||
rc = dc_device_read (rbstream->device, rbstream->address - extra, rbstream->cache, rbstream->packetsize);
|
|
||||||
if (rc != DC_STATUS_SUCCESS)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
// Move to the begin of the next packet.
|
|
||||||
rbstream->address += len;
|
|
||||||
|
|
||||||
rbstream->offset = extra + rbstream->skip;
|
|
||||||
rbstream->available = len - rbstream->skip;
|
|
||||||
rbstream->skip = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int length = rbstream->available;
|
|
||||||
if (nbytes + length > size)
|
|
||||||
length = size - nbytes;
|
|
||||||
|
|
||||||
memcpy (data + nbytes, rbstream->cache + rbstream->offset, length);
|
|
||||||
|
|
||||||
rbstream->offset += length;
|
|
||||||
rbstream->available -= length;
|
|
||||||
|
|
||||||
// Update and emit a progress event.
|
|
||||||
if (progress) {
|
|
||||||
progress->current += length;
|
|
||||||
device_event_emit (rbstream->device, DC_EVENT_PROGRESS, progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
nbytes += length;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
dc_status_t
|
|
||||||
dc_rbstream_read (dc_rbstream_t *rbstream, dc_event_progress_t *progress, unsigned char data[], unsigned int size)
|
|
||||||
{
|
|
||||||
if (rbstream == NULL)
|
|
||||||
return DC_STATUS_INVALIDARGS;
|
|
||||||
|
|
||||||
if (rbstream->direction == DC_RBSTREAM_FORWARD) {
|
|
||||||
return dc_rbstream_read_forward (rbstream, progress, data, size);
|
|
||||||
} else {
|
|
||||||
return dc_rbstream_read_backward (rbstream, progress, data, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
dc_rbstream_free (dc_rbstream_t *rbstream)
|
dc_rbstream_free (dc_rbstream_t *rbstream)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -33,14 +33,6 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
typedef struct dc_rbstream_t dc_rbstream_t;
|
typedef struct dc_rbstream_t dc_rbstream_t;
|
||||||
|
|
||||||
/**
|
|
||||||
* The ringbuffer read direction.
|
|
||||||
*/
|
|
||||||
typedef enum dc_rbstream_direction_t {
|
|
||||||
DC_RBSTREAM_FORWARD,
|
|
||||||
DC_RBSTREAM_BACKWARD
|
|
||||||
} dc_rbstream_direction_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new ringbuffer stream.
|
* Create a new ringbuffer stream.
|
||||||
*
|
*
|
||||||
@ -51,12 +43,11 @@ typedef enum dc_rbstream_direction_t {
|
|||||||
* @param[in] begin The ringbuffer begin address.
|
* @param[in] begin The ringbuffer begin address.
|
||||||
* @param[in] end The ringbuffer end address.
|
* @param[in] end The ringbuffer end address.
|
||||||
* @param[in] address The stream start address.
|
* @param[in] address The stream start address.
|
||||||
* @param[in] direction The ringbuffer read direction.
|
|
||||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||||
* on failure.
|
* on failure.
|
||||||
*/
|
*/
|
||||||
dc_status_t
|
dc_status_t
|
||||||
dc_rbstream_new (dc_rbstream_t **rbstream, dc_device_t *device, unsigned int pagesize, unsigned int packetsize, unsigned int begin, unsigned int end, unsigned int address, dc_rbstream_direction_t direction);
|
dc_rbstream_new (dc_rbstream_t **rbstream, dc_device_t *device, unsigned int pagesize, unsigned int packetsize, unsigned int begin, unsigned int end, unsigned int address);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read data from the ringbuffer stream.
|
* Read data from the ringbuffer stream.
|
||||||
|
|||||||
@ -36,7 +36,7 @@ dc_status_t
|
|||||||
reefnet_sensus_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
reefnet_sensus_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
reefnet_sensus_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
reefnet_sensus_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int devtime, dc_ticks_t systime);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,6 +48,7 @@ struct reefnet_sensus_parser_t {
|
|||||||
unsigned int maxdepth;
|
unsigned int maxdepth;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static dc_status_t reefnet_sensus_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
static dc_status_t reefnet_sensus_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime);
|
static dc_status_t reefnet_sensus_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime);
|
||||||
static dc_status_t reefnet_sensus_parser_set_atmospheric (dc_parser_t *abstract, double atmospheric);
|
static dc_status_t reefnet_sensus_parser_set_atmospheric (dc_parser_t *abstract, double atmospheric);
|
||||||
static dc_status_t reefnet_sensus_parser_set_density (dc_parser_t *abstract, double density);
|
static dc_status_t reefnet_sensus_parser_set_density (dc_parser_t *abstract, double density);
|
||||||
@ -58,6 +59,7 @@ static dc_status_t reefnet_sensus_parser_samples_foreach (dc_parser_t *abstract,
|
|||||||
static const dc_parser_vtable_t reefnet_sensus_parser_vtable = {
|
static const dc_parser_vtable_t reefnet_sensus_parser_vtable = {
|
||||||
sizeof(reefnet_sensus_parser_t),
|
sizeof(reefnet_sensus_parser_t),
|
||||||
DC_FAMILY_REEFNET_SENSUS,
|
DC_FAMILY_REEFNET_SENSUS,
|
||||||
|
reefnet_sensus_parser_set_data, /* set_data */
|
||||||
reefnet_sensus_parser_set_clock, /* set_clock */
|
reefnet_sensus_parser_set_clock, /* set_clock */
|
||||||
reefnet_sensus_parser_set_atmospheric, /* set_atmospheric */
|
reefnet_sensus_parser_set_atmospheric, /* set_atmospheric */
|
||||||
reefnet_sensus_parser_set_density, /* set_density */
|
reefnet_sensus_parser_set_density, /* set_density */
|
||||||
@ -69,7 +71,7 @@ static const dc_parser_vtable_t reefnet_sensus_parser_vtable = {
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
reefnet_sensus_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
reefnet_sensus_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int devtime, dc_ticks_t systime)
|
||||||
{
|
{
|
||||||
reefnet_sensus_parser_t *parser = NULL;
|
reefnet_sensus_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -77,7 +79,7 @@ reefnet_sensus_parser_create (dc_parser_t **out, dc_context_t *context, const un
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
parser = (reefnet_sensus_parser_t *) dc_parser_allocate (context, &reefnet_sensus_parser_vtable, data, size);
|
parser = (reefnet_sensus_parser_t *) dc_parser_allocate (context, &reefnet_sensus_parser_vtable);
|
||||||
if (parser == NULL) {
|
if (parser == NULL) {
|
||||||
ERROR (context, "Failed to allocate memory.");
|
ERROR (context, "Failed to allocate memory.");
|
||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
@ -86,8 +88,8 @@ reefnet_sensus_parser_create (dc_parser_t **out, dc_context_t *context, const un
|
|||||||
// Set the default values.
|
// Set the default values.
|
||||||
parser->atmospheric = DEF_ATMOSPHERIC;
|
parser->atmospheric = DEF_ATMOSPHERIC;
|
||||||
parser->hydrostatic = DEF_DENSITY_SALT * GRAVITY;
|
parser->hydrostatic = DEF_DENSITY_SALT * GRAVITY;
|
||||||
parser->devtime = 0;
|
parser->devtime = devtime;
|
||||||
parser->systime = 0;
|
parser->systime = systime;
|
||||||
parser->cached = 0;
|
parser->cached = 0;
|
||||||
parser->divetime = 0;
|
parser->divetime = 0;
|
||||||
parser->maxdepth = 0;
|
parser->maxdepth = 0;
|
||||||
@ -98,6 +100,35 @@ reefnet_sensus_parser_create (dc_parser_t **out, dc_context_t *context, const un
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
reefnet_sensus_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
reefnet_sensus_parser_t *parser = (reefnet_sensus_parser_t*) abstract;
|
||||||
|
|
||||||
|
// Reset the cache.
|
||||||
|
parser->cached = 0;
|
||||||
|
parser->divetime = 0;
|
||||||
|
parser->maxdepth = 0;
|
||||||
|
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dc_status_t
|
||||||
|
reefnet_sensus_parser_set_calibration (dc_parser_t *abstract, double atmospheric, double hydrostatic)
|
||||||
|
{
|
||||||
|
reefnet_sensus_parser_t *parser = (reefnet_sensus_parser_t*) abstract;
|
||||||
|
|
||||||
|
if (!ISINSTANCE (abstract))
|
||||||
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
|
parser->atmospheric = atmospheric;
|
||||||
|
parser->hydrostatic = hydrostatic;
|
||||||
|
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
reefnet_sensus_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime)
|
reefnet_sensus_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime)
|
||||||
{
|
{
|
||||||
@ -248,13 +279,13 @@ reefnet_sensus_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
|||||||
|
|
||||||
// Time (seconds)
|
// Time (seconds)
|
||||||
time += interval;
|
time += interval;
|
||||||
sample.time = time * 1000;
|
sample.time = time;
|
||||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||||
|
|
||||||
// Depth (adjusted feet of seawater).
|
// Depth (adjusted feet of seawater).
|
||||||
unsigned int depth = data[offset++];
|
unsigned int depth = data[offset++];
|
||||||
sample.depth = ((depth + 33.0 - (double) SAMPLE_DEPTH_ADJUST) * FSW - parser->atmospheric) / parser->hydrostatic;
|
sample.depth = ((depth + 33.0 - (double) SAMPLE_DEPTH_ADJUST) * FSW - parser->atmospheric) / parser->hydrostatic;
|
||||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||||
|
|
||||||
// Temperature (degrees Fahrenheit)
|
// Temperature (degrees Fahrenheit)
|
||||||
if ((nsamples % 6) == 0) {
|
if ((nsamples % 6) == 0) {
|
||||||
@ -262,7 +293,7 @@ reefnet_sensus_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
|||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
unsigned int temperature = data[offset++];
|
unsigned int temperature = data[offset++];
|
||||||
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
||||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Current sample is complete.
|
// Current sample is complete.
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user