Merge Jef's upstream changes:
- some stream IO abstraction updates: poll() support, but also a new
ioctl() interface to query the BLE name of the stream instead of our
own 'get_name()' function.
This will require corresponding changes on the subsurface side.
- Jef merged the Oceanic BLE support from me, with changes, and some
general atom2 backend cleanups.
- misc small fixups like the 3s Mares BLE timeout we already had.
* git://github.com/libdivecomputer/libdivecomputer:
Install the ioctl header file
Advertise the BLE support in the device descriptors
Fix the BLE device detection for the i770R and Pro Plus X
Implement the BLE handshaking
Implement the BLE packet sending and receiving
Read the entire data packet in a single operation
Remove the trailing zero byte from all commands
Fix a bug in the ACK/NAK handling
Remove an unnecessary function
Add an ioctl to retrieve the remote device name
Re-implement the set_latency function as an ioctl
Add an ioctl function to the I/O interface
Integrate the new poll function
Add a poll function to the I/O interface
Add support for the Oceanic Veo 4.0
Increase the timeout to 3 seconds
The set_latency function is the perfect example of a feature that should
be implemented as an ioctl: it's only implemented by a single driver,
and the functionality is also highly platform specific.
This new ioctl function allows to perform I/O stream specific requests
through a generic interface. This provides an easy way to extend the I/O
interface with some driver specific features, without having to modify
the public api.
The Linux implementation is very straighforward and just a lightweight
wrapper around the select function. But the Windows implementation is
much more complex, because the Windows event notification mechanism
behaves very different:
The WaitCommEvent function does not support a timeout and is always a
blocking call. The only way to implement a timeout is to use
asynchronous I/O (or overlapped I/O as it's called in the Windows API),
to run the operation in the background. This requires some additional
book keeping to keep track of the pending background operation.
The event mechanism is also edge triggered instead of level triggered,
and reading the event with the WaitCommEvent function clears the pending
event. Therefore, the state of the input buffer needs to be checked with
the ClearCommError function before and after the WaitCommEvent call.
The check before is necessary in case the event is already cleared by a
previous WaitCommEvent call, while there is still data present in the
input buffer. In this case, WaitCommEvent should not be called at all,
because it would wait until more data arrives.
The check afterwards is necessary in case WaitCommEvent reports a
pending event, while the data in the input buffer has already been
consumed. In this case, the current event must be ignored and
WaitCommEvent needs to be called again, to wait for the next event.
Merge upstream libdivecomputer updates from Jef.
Misc small updates all over, the biggest thing (code wise) is probably
the Ratio firmware update support.
* 'master' of git://github.com/libdivecomputer/libdivecomputer:
Fix the Oceanic Geo 4.0 memory layout
Ignore all empty logbook entries
Add a workaround for the hwOS ppO2 firmware bug
Use macros to encode the firmware version
Use symbolic constants for the sample types
Remove the obsolete hwos parameter
Limit the tank pressure workaround to hwOS devices
Fix the OSTC tank pressure decoding
Fix the Scubapro G2 HUD udev rule
Add the Mares Genius to the bluetooth filter
Add firmware upgrade support for the Ratio computers
This does nothing at all, but it adds all the core skeleton
infrastructure for the Deepblu Cosmiq+ dive computer.
Let's see if I can make sense of things and make it download anything.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This logs every INFO_EVENT record and provides a SAMPLE_EVENT_BOOKMARK event for
the only INFO_EVENT we can parse so far, the TAG event. Three bits in the flag
value in that event structure are now used to hold the tag type, and if a
non-zero type has been set, then the value is the heading in degress.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Update with Jef's upstream:
- add support for Cressi Goa and Cartesio
- update the Shearwater PNF parser to Jef's version
- misc minor fixes
* git://github.com/libdivecomputer/libdivecomputer:
Use the timezone setting of the dive computer
Add support for the Cressi Goa and Cartesio
Add an extra parameter for the initial CRC value
Add support for the Ratio iDive Color series
Shearwater Petrel Native Format parsing
Shearwater: detect which logbook format is support
Shearwater: add Teric to list of supported dive computers
Shearwater: skip deleted dives
Fix a potential buffer overflow
Some of the transport types have meaningful names.
The BLE transport has a device name that was exposed during device
discovery, for example, and some back-ends (ok, right now only the
Aqualung i300C and i770R) need to know what that device name was in
order to handshake with the device properly.
Other transports, like the USBSTORAGE one, could usefully use this to
get the basename of the path to the storage, although right now that
transport makes do with simply doing a "dc_iostream_read()" on the
transport instead.
For now, this is just the infrastructure, ready to get hooked into.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Several dive computers support this, so why not have the proper
interface for it in libdivecomputer?
Triggered by the fact that the Python scripts to generate XML files from
the Garmin FIT files can import this information, but the native
libdivecomputer model couldn't.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Merge the initial Garmin Descent Mk1 support.
This actually works well enough to be useful, even though there are a
few ugly details yet to be sorted out.
The download itself is fairly complete, but all event handling is
currently missing (warnings, gas changes, things like that).
Also, because of how libdivecomputer works, the "downloading" of dives
is entirely separate from the "parsing" of dives in the libdivecomputer
world. And that is actually problematic for the Garmin Descent
downloader, because you actually need to parse the data to even figure
out whether it's actually a dive at all!
The Garmin Descent is also a fitness and general excercise tracker, so
people can (and do) use it for other sports than just diving, and so the
activities we download may end up not being dives at all, but other
events.
But before we parse them, we don't know, and we aren't really supposed
to parse them until after we've passed the data to the application and
it passes it back for parsing. Nasty chicken-and-egg problem there..
So right now non-diving activities will just show up as very short
and/or shallow dives.
This is fixable by just parsing things an extra time, but I really wish
libdivecomputer would just stop thinking that downloading and parsing
are separate events.
* garmin-descent:
Add dc_usb_storage_open to the symbols list
garmin: only record gasmixes for cylinders that aren't enabled
garmin: don't emit fake device info and vendor event
garmin: add support for downloading gas mixes
garmin: add GPS coordinate data and improve parser_get_field() reports
garmin: actually start using the parsed data
garmin: turn all the remaining unrecognized fields into DEBUG messages
garmin: add a lot of new field definitions
garmin: teach the parser to show undefined values for unknown fields too
garmin: fix file length header parsing
garmin: teach the parser about invalid values and more dates
garmin: some fields are defined in all message types
Garmin: start parsing definition records
Garmin Descent Mk1: flesh out the actual downloading part
Add Garmin Descent Mk1 skeleton
Add 'USB storage' transport enumeration
Merge upstream libdivecomputer changes from Jef Driesen.
* https://github.com/libdivecomputer/libdivecomputer:
Add Travis CI integration
Fix the transport command-line parameter
Document dc_descriptor_get_model
Include stddef.h in iostream.h
Add support for the Mares Smart Air
Fix the average depth for older OSTC dives
Add support for the Oceanic Pro Plus X
This does absolutely nothing, but it adds the basic skeleton for a new
dive computer support.
Not only don't I have any real code for any of this yet, but I actually
think it might be useful to have a "this is how to add a new dive
computer" example commit.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
We now have at least two dive computers that enumerate as USB storage
devices: the Uemis Zurich and the Garmin Descent Mk1.
The Uemis is handled purely inside of subsurface, with no
libdivecomputer support. That was likely a mistake, but it was not
practical to do a libdivecomputer backend for it at the time.
The Garmin Descent Mk1 support would be much nicer to have natively in
libdivecomputer, and looks much more relevant and practical than the
Uemis situation was.
So start off with defining a new transport type.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Merge with upstream libdivecomputer from Jef.
This fixes some sleeping functions, and also implements support for the
Tecdiving DiveComputer.eu dive computers.
There's also various minor cleanups. Most notable is perhaps the
unification of the Uwatec dive computer backends.
* git://github.com/libdivecomputer/libdivecomputer:
Initialize the socket library for the bluetooth discovery
Fix the length of the Suunto D6i gas change event
Add support for the Tecdiving DiveComputer.eu
Fix the Mac OS X timer implementation
Add the average depth to the xml output
Skip the handshake for BLE communication
Unify the Uwatec Smart, Meridian and G2 backends
Re-organize the packet send/receive code
Use symbolic constants for the commands
Implement an rfcomm filter function
Remove the filter for HW OSTC's without bluetooth
Implement the sleep function for IrDA and bluetooth
The Uwatec Smart, Meridian and G2 backends are almost identical, except
for the low-level packet sending and receiving code. With the new I/O
layer, those three backends can easily be unified in a single backend.
The Meridian and G2 are completely removed, only the family types are
kept for backwards compatibility.
This extends the libdivecomputer notion of "dc_tankvolume_t" to not just
have the tank volume type (imperial or metric), but be a "dc_tankinfo_t"
that shows other information about the cylinder.
The imperial-vs-metric data remains the same two values:
1 - metric
2 - imperial
but instead of being an enumeration of volume types, it is extended to a
bitmap of tank information, and the other bits currently are
4 - CC diluent cylinder
8 - CC O2 cylinder
with possible future extensions (bailout gas, perhaps).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
The default libdivecomputer fields are good for structured data that has
a well-defined format, like the cylinder information, or the temperature
data.
But it is entirely useless for miscellaneous divecomputer-specific
information, where there is no standard way of representing the data
across different kinds of dive computers.
Examples of this include simple things like deco calculation algorithm
(what kind of Buehlmann, gradient factor information or is it some
vendor-specific mode?) and even something as trivial as a serial number.
No, serial numbers aren't numbers. They are strings. Really.
But this also includes much more complex data that is really specific to
a particular dive computer or family: what the battery status is for the
dive computer or the wireless transmitters it is connected to (sometimes
it's a voltage, sometimes it's a percentage, sometimes it's just "good"
or "marginal").
It also includes random incidental information like firmware version
numbers (again, these are strings, not numbers, despite the name) or
dive mode and personal adjustment information.
So allow the dive computer to just give "extra information" in the form
of an array of { key, value } string pairs. For my Perdix AI the
information could be
{ "Serial", "370d1f24" }
{ "FW Version", "44" }
{ "Deco model", "GF 40/85" }
{ "Battery type", "3.6V Saft" }
{ "Battery at end", "3.4 V" }
and for my EON Steel with three wireless transmitters connected it can
look like this:
{ "Serial", "1742104730" }
{ "FW Version", "1.6.5" }
{ "HW Version", "70.3.0" }
{ "Battery at start", "Charge: 83%, Voltage: 4.012V" }
{ "Deco algorithm", "Suunto Fused RGBM" }
{ "Personal Adjustment", "P-2" }
{ "Battery at end", "Charge: 79%, Voltage: 3.977V" }
{ "Dive Mode", "Trimix" }
{ "Desaturation Time", "7:53" }
{ "Transmitter ID", "1519107801" }
{ "Transmitter Battery at start", "87 %" }
{ "Transmitter Battery at end", "87 %" }
{ "Transmitter ID", "1550110028" }
{ "Transmitter Battery at start", "100 %" }
{ "Transmitter Battery at end", "100 %" }
{ "Transmitter ID", "1719102387" }
{ "Transmitter Battery at start", "100 %" }
{ "Transmitter Battery at end", "100 %" }
so this data is inherently unstructured and dependent on the dive
computer, but quite relevant to the diver. Subsurface shows this in the
"Extra Info" panel for each dive computer.
Also teach the example output-xml code about the new string field
extension. That example output-xml code was written by Anton Lundin in
the old Subsurface branch, and signed-off-by Dirk. The sign-offs here
are taken from that original work.
Signed-off-by: Anton Lundin <glance@acc.umu.se>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
We _really_ find the standard libdivecomputer event enumeration much too
inflexible and not giving us enough useful information. This is
particularly noticeable with the Suunto EON Steel/Core, where there are
no fixed event enumerations, but instead the dive computer literally
gives you event strings.
Do the same thing in the libdivecomputer interface: allow an event of
type SAMPLE_EVENT_STRING which instead of the useless "value" gives an
actual string describing the event.
Also, extend the "flags" field to have not just a NONE/BEGIN/END marker,
but a severity level. The severity level is 3 bits, so 0-7, with the meaning being
0 - 'no severity info'
1 - state change (so 'surface' event or similar - don't even show it by default)
2 - notification (informational, eg "safety stop", "tank change")
3 - warning ("ascent speed")
4 - alarm (some actual dive violation).
5-7: future expansion?
Think of 0 as "legacy - missing information", 1 as "internal DC thing",
and 2-4 as (green-yellow-red).
This makes it possible for the dive computer back-end to give the user
actual useful information for events.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
When two or more identical (or very similar) dive computers are
connected, the USB VID/PID can be ambiguous. That's because the VID/PID
identifies the type of the USB device, and not the individual device.
But each USB HID device descriptor returned by the device discovery
represents a single connected device, and thus guarantees to open the
correct USB device.
To obtain the same behaviour as before, an application can simply open
the first discovered device.
Currently the dive computer backends are responsible for opening (and
closing) the underlying I/O stream internally. The consequence is that
each backend is hardwired to a specific transport type (e.g. serial,
irda or usbhid). In order to remove this dependency and support more
than one transport type in the same backend, the opening (and closing)
of the I/O stream is moved to the application.
The dc_device_open() function is modified to accept a pointer to the I/O
stream, instead of a string with the device node (which only makes sense
for serial communication). The dive computer backends only depend on the
common I/O interface.
With the support for multiple transports per device, the
dc_descriptor_get_transport() function became obsolete because it does
support only a single transport type. Applications should use the new
dc_descriptor_get_transports() function instead.
Because the list of supported built-in transports depends on the
availability of external libraries (libusb, hidapi) and the operating
system, the application needs some mechanism to retrieve this
information at runtime. Therefore, a new dc_context_get_transports()
function is added, which returns a bitmask with all the available
built-in transports.
Several dive computers support multiple transports. For example the
Suunto Eon Steel supports both USB HID and BLE. All devices using
bluetooth classic communication support both the native bluetooth
transport and the legacy serial port emulation.
To support this feature, the values of the dc_transport_t type are
changed into bitmasks, and the dc_descriptor_t struct is extended with a
bitfield with all the supported transports.
Add a function to query the underlying transport type. This allows the
dive computer backends to implement transport specific behaviour where
necessary.
For the built-in I/O implementations, the transport type is obviously
always hardcoded, but for a custom I/O implementation the application
needs to provide the correct type. Hence the transport type can't be
hardcoded in the vtable and needs to be passed as a parameter.
Add a new type to distinguish between closed circuit (CCR) and
semi-closed circuit (SCR) diving. Some dive computers from HW and
DiveSystem/Ratio support this.
Because the CCR/SCR abbreviations are more commonly used, let's take the
opportunity to also rename the existing DC_DIVEMODE_CC. To preserve
backwards compatibility, a macro is added to map the old name to the new
one.
Reported-by: Jan Mulder <jlmulder@xs4all.nl>
The purpose of the new I/O interface is to provide a common interface
for all existing I/O implementations (serial, IrDA, bluetooth and USB
HID). With a common interface the dive computer backends can more easily
use different I/O implementations at runtime, without needing
significant code changes. For example bluetooth enabled devices can
easily switch between native bluetooth communication and serial port
emulation mode.
The new interface is modelled after the existing serial communication
api. Implementations where some of those functions are meaningless (e.g.
IrDA, bluetooth and USB), can just leave those functions unimplemented
(causing the call to fail with DC_STATUS_UNSUPPORTED), or implement it
as a no-op (always return DC_STATUS_SUCCESS).
Allthough most dive computers always use local time and don't support
timezones at all, there are a few exceptions. There are two different
sources of timezone information:
- Some of the newer Uwatec/Scubapro devices use UTC internally and also
support a timezone setting. This UTC offset is currently taken into
account to obtain the dive date/time, but the UTC offset itself is
lost.
- Uwatec/Scubapro and Reefnet devices rely on the clock of the host
system to synchronize the internal device clock and calculate the
dive date/time. The consequence is that the resulting date/time is
always in the timezone of the host system.
In order to preserve this timezone information, the dc_datetime_t
structure is extended with a new "timezone" field, containing the UTC
offset in seconds. Devices without timezone support will set the field
to the special value DC_TIMEZONE_NONE.
The dc_datetime_localtime() and dc_datetime_gmtime() functions will
automatically populate the new field with respectively the local
timezone offset and zero. The dc_datetime_mktime() function will take
into account the new timezone field for the conversion to UTC. The
special value DC_TIMEZONE_NONE is interpreted as zero.
Being able to synchronize the dive computer clock with the host system
is a very useful feature. Add the infrastructure to support this feature
through the public api.
The back-end parser seems to be the same as for the Uwatec Smart (aka
Galileo Sol). At least that's the assumption right now.
The downloader just uses USB HID (very similar to EON Steel) rather than
the horrible IrDA thing.
There's also eventually a BLE thing, but that's for the future.
This is an unholy mixture of the Uwatec Smart downloader logic and the
EON Steel usbhid transfer code. The back-end is pure Uwatec Smart
(model 0x11, same as Galileo Sol).
I'm not at all sure this gets everything right, but it downloads
*something*.
[Jef Driesen: Renamed the backend to uwatec, and made some smaller
cosmetic changes to match the existing coding style.]
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
The vendor_product_parser_create() and vendor_product_device_open()
functions should be called indirectly, through the generic
dc_device_open() and dc_parser_new() functions. And the
vendor_product_extract_dives() functions are internal functions that
should never have been part of the public api in the first place.
The current algorithm always downloads a full memory dump, and extracts
the dives afterwards. For the typical scenario where only a few dives
are being downloaded, this is inefficient because most of the data isn't
needed. This can easily be avoided by downloading the data on the fly.
The Cressi Drake is a mainly a freedive computer. The data format is
almost identical to the Leonardo. The main difference is that a single
dive now contains an entire freedive session. Each freedive in the
session is delimited with a 4 byte header containing the surface
interval and a special marker.
To be able to pass the OSTC 3 model number to the parser, and preserve
backwards compatibility, we need a new function. The new function should
also be used for the Frog, by passing zero as the model number.
Using the hw_ostc_parser_create() function with the hwos parameter set
to one, is now deprecated but will remain supported for backwards
compatibility.
The frog parameter and field are not only used for the Frog, but also
for all hwOS based models. Therefore, using the more generic hwos as the
name is more meaningful.
For applications supporting offline parsing (like libdivecomputer's own
dctool application), some device specific knowledge is still required in
order to map a particular model to the corresponding backend. The new
convenience function will take care of that internally.
The already existing dc_parser_new() function does the same, but
requires an open device handle, which makes it unsuitable for offline
parsing.