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.
The low level serial and IrDA functions are modified to:
- Use the libdivecomputer namespace prefix.
- Return a more detailed status code instead of the zero on success and
negative on error return value. This will allow to return more
fine-grained error codes.
- The read and write functions have an additional output parameter to
return the actual number of bytes transferred. Since these functions
are not atomic, some data might still be transferred successfully if
an error occurs.
The dive computer backends are updated to use the new api.
Both the allocation and initialization of the object data structure is
now moved to a single function. The corresponding deallocation function
is intended to free objects that have been allocated, but are not fully
initialized yet. The public cleanup function shouldn't be used in such
case, because it may try to release resources that haven't been
initialized yet.
For the Nemo Air, a dive mode with the value 2 indicates gauge mode
instead of freedive mode. With this change, all models from the puck
family now use the same values.
The term "backend" can be confusing because it can refer to both the
virtual function table and the device/parser backends. The use of the
term "vtable" avoids this.
If the first attempt fails, that might indicate the device isn't ready
yet to service requests. In that case immediately retrying again isn't
the right solution. Adding a small delay seems to increase the success
rate, so it's a good idea anyway, regardless of the underlying reason.
These macros are used internally and don't need to be exposed. In some
cases, the actual values are not even constant, but dependant on the
model and/or the firmware version.
I forgot to update the device and parser initialization functions to
store the context pointer into the objects. As a result, the internal
context pointers were always NULL.
The public api is changed to require a context object for all
operations. Because other library objects store the context pointer
internally, only the constructor functions need an explicit context
object as a parameter.
Adding the "dc_" namespace prefix (which is of course an abbreviation
for libdivecomputer) should avoid conflicts with other libraries. For
the time being, only the high-level device and parser layers are
changed.
The public header files are moved to a new subdirectory, to separate
the definition of the public interface from the actual implementation.
Using an identical directory layout as the final installation has the
advantage that the example code can be build outside the project tree
without any modifications to the #include statements.
We received a report of a Darwin Air device which has a very high error
rate. The majority of the echo packets is incorrect, but since this
doesn't seem to have any effect on the actual data packet, we can just
ignore this error. If there happens to be a more serious error, it will
be detect in the data packet.
Sometimes there were also a some garbage bytes received at startup.
Adding a small delay seems to fix this.
When trying to send the commands as fast as possible, without any delay,
the failure rate is very high. Almost every single packet fails with a
timeout at first. Retrying the packet works, but those many timeouts
make the download extremely slow. Adding a small delay avoids the much
more expensive timeout and speeds up the transfer significantly.
The common device structure was used only for sharing the fingerprint
and layout descriptor, but the nemo backend doesn't even store a layout
descriptor, and the fingerprint can equally well be passed around as a
function argument.
The memory layout of the Mares Puck and Nemo devices is very similar,
which allows to share the parsing code between the backends.
The Mares Puck protocol allows for a more efficient implementation, by
reading only the data that we really need. But as an intermediate
solution, reusing the Nemo code is good enough.