diff --git a/.gitignore b/.gitignore index f97ad37..aa31142 100644 --- a/.gitignore +++ b/.gitignore @@ -37,33 +37,7 @@ Makefile.in /doc/html/ /doc/latex/ -/examples/aladin -/examples/atom2 -/examples/d9 -/examples/darwin /examples/dctool -/examples/edy -/examples/eon -/examples/frog -/examples/iconhd -/examples/leonardo -/examples/memomouse -/examples/n2ition3 -/examples/nemo -/examples/ostc -/examples/ostc-fwupdate -/examples/predator -/examples/puck -/examples/sensus -/examples/sensuspro -/examples/sensusultra -/examples/smart -/examples/solution -/examples/universal -/examples/veo250 -/examples/vtpro -/examples/vyper -/examples/vyper2 /include/libdivecomputer/version.h diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am index 7108446..63f9e85 100644 --- a/doc/man/Makefile.am +++ b/doc/man/Makefile.am @@ -17,6 +17,7 @@ MANPAGES = \ dc_descriptor_get_model.3 \ dc_descriptor_get_product.3 \ dc_descriptor_get_vendor.3 \ + dc_descriptor_get_transports.3 \ dc_descriptor_iterator.3 \ dc_device_close.3 \ dc_device_foreach.3 \ @@ -32,7 +33,29 @@ MANPAGES = \ dc_parser_new.3 \ dc_parser_samples_foreach.3 \ dc_parser_set_data.3 \ - libdivecomputer.3 + dc_bluetooth_open.3 \ + dc_bluetooth_iterator_new.3 \ + dc_bluetooth_device_get_address.3 \ + dc_bluetooth_device_get_name.3 \ + dc_bluetooth_addr2str.3 \ + dc_bluetooth_str2addr.3 \ + dc_bluetooth_device_free.3 \ + dc_usbhid_open.3 \ + dc_usbhid_device_get_pid.3 \ + dc_usbhid_device_get_vid.3 \ + dc_usbhid_iterator_new.3 \ + dc_usbhid_device_free.3 \ + dc_serial_open.3 \ + dc_serial_device_get_name.3 \ + dc_serial_iterator_new.3 \ + dc_serial_device_free.3 \ + dc_irda_open.3 \ + dc_irda_device_get_name.3 \ + dc_irda_device_get_address.3 \ + dc_irda_iterator_new.3 \ + dc_irda_device_free.3 \ + dc_iostream_close.3 \ + libdivecomputer.3 HTMLPAGES = $(MANPAGES:%=%.html) diff --git a/doc/man/dc_bluetooth_addr2str.3 b/doc/man/dc_bluetooth_addr2str.3 new file mode 100644 index 0000000..ea073c3 --- /dev/null +++ b/doc/man/dc_bluetooth_addr2str.3 @@ -0,0 +1,61 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_BLUETOOTH_ADDR2STR 3 +.Os +.Sh NAME +.Nm dc_bluetooth_addr2str +.Nd Convert a bluetooth address to a string. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/bluetooth.h +.Ft "const char*" +.Fo dc_bluetooth_addr2str +.Fa "dc_bluetooth_address_t address" +.Fa "char *str" +.Fa "size_t size" +.Fc +.Sh DESCRIPTION +Convert a bluetooth address to a string. +.Pp +The bluetooth address is formatted as XX:XX:XX:XX:XX:XX, where each XX is a +hexadecimal number specifying an octet of the 48-bit address. +The minimum size for the buffer is +.Dv DC_BLUETOOTH_SIZE +bytes. +.Pp +The reverse can be done with +.Xr dc_bluetooth_str2addr 3 . +.Sh RETURN VALUES +Returns the bluetooth address represented as a string. +.Sh SEE ALSO +.Xr dc_bluetooth_str2addr 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_bluetooth_device_free.3 b/doc/man/dc_bluetooth_device_free.3 new file mode 100644 index 0000000..fd29096 --- /dev/null +++ b/doc/man/dc_bluetooth_device_free.3 @@ -0,0 +1,52 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_BLUETOOTH_DEVICE_FREE 3 +.Os +.Sh NAME +.Nm dc_bluetooth_device_free +.Nd Destroy the bluetooth device and free all resources. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/bluetooth.h +.Ft void +.Fo dc_bluetooth_device_free +.Fa "dc_bluetooth_device_t *device" +.Fc +.Sh DESCRIPTION +Destroy the bluetooth device and free all resources. +The bluetooth +.Fa device +usually found by searching through +.Xr dc_bluetooth_iterator_new 3 . +.Sh SEE ALSO +.Xr dc_bluetooth_iterator_new 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_bluetooth_device_get_address.3 b/doc/man/dc_bluetooth_device_get_address.3 new file mode 100644 index 0000000..c7c1c63 --- /dev/null +++ b/doc/man/dc_bluetooth_device_get_address.3 @@ -0,0 +1,69 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_BLUETOOTH_DEVICE_GET_ADDRESS 3 +.Os +.Sh NAME +.Nm dc_bluetooth_device_get_address +.Nd Get the address of a bluetooth device. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/bluetooth.h +.Ft "dc_bluetooth_address_t" +.Fo dc_bluetooth_device_get_address +.Fa "dc_bluetooth_device_t *device" +.Fc +.Sh DESCRIPTION +Get the bluetooth device address of given bluetooth +.Fa device . +Required when opening transport communication with +.Xr dc_bluetooth_open 3 . +Requires a valid +.Fa device +of type +.Ft dc_bluetooth_device_t +which can be retrieved using +.Xr dc_bluetooth_iterator_new 3 . +.Sh RETURN VALUES +Returns the bluetooth address of +.Fa device +as +.Ft dc_bluetooth_address_t +which is a 64bit integer holding the bluetooth address. + +The address can be formatted as a string by using +.Xr dc_bluetooth_addr2str 3 . +.Sh SEE ALSO +.Xr dc_bluetooth_open 3 , +.Xr dc_bluetooth_iterator_new 3 , +.Xr dc_bluetooth_device_get_name 3 , +.Xr dc_bluetooth_addr2str 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_bluetooth_device_get_name.3 b/doc/man/dc_bluetooth_device_get_name.3 new file mode 100644 index 0000000..c7f7da6 --- /dev/null +++ b/doc/man/dc_bluetooth_device_get_name.3 @@ -0,0 +1,61 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_BLUETOOTH_DEVICE_GET_NAME 3 +.Os +.Sh NAME +.Nm dc_bluetooth_device_get_name +.Nd Get the name of a bluetooth device. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/bluetooth.h +.Ft "const char *" +.Fo dc_bluetooth_device_get_name +.Fa "dc_bluetooth_device_t *device" +.Fc +.Sh DESCRIPTION +Get the name of given bluetooth +.Fa device . +Used for displaying. +Requires a valid +.Fa bluetooth_device +of type +.Ft dc_bluetooth_device_t +which can be retrieved using +.Xr dc_bluetooth_iterator_new 3 . +.Sh RETURN VALUES +Returns the bluetooth device of +.Fa device . +.Sh SEE ALSO +.Xr dc_bluetooth_open 3 , +.Xr dc_bluetooth_iterator_new 3 , +.Xr dc_bluetooth_device_get_address 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_bluetooth_iterator_new.3 b/doc/man/dc_bluetooth_iterator_new.3 new file mode 100644 index 0000000..e532206 --- /dev/null +++ b/doc/man/dc_bluetooth_iterator_new.3 @@ -0,0 +1,102 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_BLUETOOTH_ITERATOR_NEW 3 +.Os +.Sh NAME +.Nm dc_bluetooth_iterator_new +.Nd Create an iterator to enumerate the bluetooth devices. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/bluetooth.h +.Ft dc_status_t +.Fo dc_bluetooth_iterator_new +.Fa "dc_iterator_t **iterator" +.Fa "dc_context_t *context" +.Fa "dc_descriptor_t *descriptor" +.Fc +.Sh DESCRIPTION +Iterates through the available bluetooth devices which matches the given +.Fa descriptor . +Accepts a +.Fa context +opened with +.Xr dc_context_new 3 +and a +.Fa descriptor +usually found by searching through +.Xr dc_descriptor_iterator 3 . +.Pp +On returning +.Dv DC_STATUS_SUCCESS +the +.Fa iterator +will be set to an +.Ft dc_iterator_t +which can be used to iterate the available bluetooth devices using +.Xr dc_iterator_next 3 . +.Pp +The value type of the iterator is of type +.Ft dc_bluetooth_device_t . +This value can be used in functions to extract information about this specific bluetooth device, namely +.Xr dc_bluetooth_device_get_name 3 +and +.Xr dc_bluetooth_device_get_address 3 . +When done the bluetooth device needs to be freed with +.Xr dc_bluetooth_device_free 3 . +.Pp +After iterating the +.Fa iterator +needs to be freed using +.Xr dc_iterator_free 3 . + +.Sh RETURN VALUES +Returns +.Dv DC_STATUS_SUCCESS +on success, or another +.Ft dc_status_t +code on failure. + +On +.Dv DC_STATUS_SUCCESS +the returned +.Fa iterator +needs to be freed when done using +.Xr dc_iterator_free 3 . +.Sh SEE ALSO +.Xr dc_context_new 3 , +.Xr dc_usbhid_iterator_new 3 , +.Xr dc_serial_iterator_new 3 , +.Xr dc_irda_iterator_new 3 , +.Xr dc_bluetooth_device_get_name 3 , +.Xr dc_bluetooth_device_get_address 3 , +.Xr dc_bluetooth_device_free 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_bluetooth_open.3 b/doc/man/dc_bluetooth_open.3 new file mode 100644 index 0000000..6764ece --- /dev/null +++ b/doc/man/dc_bluetooth_open.3 @@ -0,0 +1,87 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_BLUETOOTH_OPEN 3 +.Os +.Sh NAME +.Nm dc_bluetooth_open +.Nd Opens an iostream for a bluetooth device +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/bluetooth.h +.Ft dc_status_t +.Fo dc_bluetooth_open +.Fa "dc_iostream_t **iostream" +.Fa "dc_context_t *context" +.Fa "dc_bluetooth_address_t address" +.Fa "unsigned int port" +.Fc +.Sh DESCRIPTION +Opens an iostream for a bluetooth device. +Accepts a +.Fa context +opened with +.Xr dc_context_new 3 , +a 48-bit bluetooth +.Fa address +given by +.Xr dc_bluetooth_iterator_new 3 +together with +.Xr dc_bluetooth_device_get_address 3 +or +.Xr dc_bluetooth_str2addr 3 +and a bluetooth rfcomm +.Fa port +number (use 0 for autodetection). +.Pp +Upon returning +.Dv DC_STATUS_SUCCESS , +the +.Fa iostream +pointer must be freed with +.Xr dc_iostream_close 3 . +.Sh RETURN VALUES +Returns +.Dv DC_STATUS_SUCCESS +on success or one of several error values on error. +On success, the +.Fa iostream +pointer is filled in with an open handle. +.Sh SEE ALSO +.Xr dc_context_new 3 , +.Xr dc_iostream_close 3 , +.Xr dc_serial_open 3 , +.Xr dc_irda_open 3 , +.Xr dc_usbhid_open 3 , +.Xr dc_bluetooth_iterator_new 3 , +.Xr dc_bluetooth_device_get_address 3 , +.Xr dc_bluetooth_str2addr 3 , +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_bluetooth_str2addr.3 b/doc/man/dc_bluetooth_str2addr.3 new file mode 100644 index 0000000..19ad357 --- /dev/null +++ b/doc/man/dc_bluetooth_str2addr.3 @@ -0,0 +1,58 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_BLUETOOTH_STR2ADDR 3 +.Os +.Sh NAME +.Nm dc_bluetooth_str2addr +.Nd Convert a string to a bluetooth address. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/bluetooth.h +.Ft "dc_bluetooth_address_t" +.Fo dc_bluetooth_addr2str +.Fa "const char *address" +.Fc +.Sh DESCRIPTION +Convert a string to a bluetooth address. +.Pp +The string +.Fa address +is expected to be in the format XX:XX:XX:XX:XX:XX, +where each XX is a hexadecimal number specifying an octet of the 48-bit address. +.Pp +The reverse can be done with +.Xr dc_bluetooth_addr2str 3 . +.Sh RETURN VALUES +Returns the bluetooth address represented as a 48-bit number. +.Sh SEE ALSO +.Xr dc_bluetooth_addr2str 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_descriptor_get_transports.3 b/doc/man/dc_descriptor_get_transports.3 new file mode 100644 index 0000000..93bef41 --- /dev/null +++ b/doc/man/dc_descriptor_get_transports.3 @@ -0,0 +1,72 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_DESCRIPTOR_GET_TRANSPORTS 3 +.Os +.Sh NAME +.Nm dc_descriptor_get_transports +.Nd Gets the transports supported by the given descriptor. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/descriptor.h +.Ft "unsigned int" +.Fo dc_descriptor_get_transports +.Fa "dc_descriptor_t *descriptor" +.Fc +.Sh DESCRIPTION +Gets the transports supported by the given +.Fa descriptor . +The +.Fa descriptor +usually found by searching through +.Xr dc_descriptor_iterator 3 . +.Sh RETURN VALUES +Returns a union (bitwise OR) of the transports supported by the given +.Fa descriptor . +.Pp +The result is combination of +.Dv DC_TRANSPORT_USB , +.Dv DC_TRANSPORT_USBHID , +.Dv DC_TRANSPORT_BLE , +.Dv DC_TRANSPORT_BLUETOOTH , +.Dv DC_TRANSPORT_SERIAL , +.Dv DC_TRANSPORT_IRDA +.Pp +To determine if a specific transport is supported use the following code +.Bd -literal -offset indent +unsigned int transports = dc_descriptor_get_transports(descriptor); +if(transports & DC_TRANSPORT_USBHID) { + // Device supports USB HID as transport +} +.Ed +.Sh SEE ALSO +.Xr dc_descriptor_iterator 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_device_open.3 b/doc/man/dc_device_open.3 index 265d129..3ba335f 100644 --- a/doc/man/dc_device_open.3 +++ b/doc/man/dc_device_open.3 @@ -18,7 +18,7 @@ .\" Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, .\" MA 02110-1301 USA .\" -.Dd January 5, 2017 +.Dd June 5, 2020 .Dt DC_DEVICE_OPEN 3 .Os .Sh NAME @@ -33,7 +33,7 @@ .Fa "dc_device_t **device" .Fa "dc_context_t *context" .Fa "dc_descriptor_t *descriptor" -.Fa "const char *name" +.Fa "dc_iostream_t *iostream" .Fc .Sh DESCRIPTION Open a dive computer device for processing. @@ -45,19 +45,14 @@ a dive computer .Fa descriptor usually found by searching through .Xr dc_descriptor_iterator 3 , -and a platform-specific device -.Fa name -.Po -such as -.Pa /dev/ttyUSBx -on Linux, -.Pa /dev/tty.xxx -on Mac OS X, -.Pa /dev/ttyUx -on the BSDs, +and a +.Fa iostream +opened with a transport specific open function like +.Xr dc_usbhid_open 3 , +.Xr dc_irda_open 3 , +.Xr dc_serial_open 3 , or -.Pa COMx -on Microsoft Windows +.Xr dc_bluetooth_open 3 .Pc . .Pp Upon returning @@ -83,6 +78,10 @@ The library was written by .An Jef Driesen , .Mt jef@libdivecomputer.org . +.br The manpages were written by .An Kristaps Dzonsons , .Mt kristaps@bsd.lv . +and +.An Vincent Hagen , +.Mt vinnie@script4web.nl \ No newline at end of file diff --git a/doc/man/dc_iostream_close.3 b/doc/man/dc_iostream_close.3 new file mode 100644 index 0000000..2f3b67b --- /dev/null +++ b/doc/man/dc_iostream_close.3 @@ -0,0 +1,60 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_IOSTREAM_CLOSE 3 +.Os +.Sh NAME +.Nm dc_iostream_close +.Nd Close the I/O stream and free all resources. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/iostream.h +.Ft dc_status_t +.Fo dc_iostream_close +.Fa "dc_iostream_t *iostream" +.Fc +.Sh DESCRIPTION +Close the I/O stream and free all resources. +Accepts the +.Fa iostream +to close and free. +.Sh RETURN VALUES +Returns +.Dv DC_STATUS_SUCCESS +on success, or another +.Ft dc_status_t +code on failure. +.Sh SEE ALSO +.Xr dc_usbhid_open 3 , +.Xr dc_serial_open 3 , +.Xr dc_irda_open 3 , +.Xr dc_bluetooth_open 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_irda_device_free.3 b/doc/man/dc_irda_device_free.3 new file mode 100644 index 0000000..bf0926f --- /dev/null +++ b/doc/man/dc_irda_device_free.3 @@ -0,0 +1,52 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_IRDA_DEVICE_FREE 3 +.Os +.Sh NAME +.Nm dc_irda_device_free +.Nd Destroy the irda device and free all resources. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/irda.h +.Ft void +.Fo dc_irda_device_free +.Fa "dc_irda_device_t *device" +.Fc +.Sh DESCRIPTION +Destroy the irda device and free all resources. +The irda +.Fa device +usually found by searching through +.Xr dc_irda_iterator_new 3 . +.Sh SEE ALSO +.Xr dc_irda_iterator_new 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_irda_device_get_address.3 b/doc/man/dc_irda_device_get_address.3 new file mode 100644 index 0000000..6cf4323 --- /dev/null +++ b/doc/man/dc_irda_device_get_address.3 @@ -0,0 +1,59 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_IRDA_DEVICE_GET_ADDRESS 3 +.Os +.Sh NAME +.Nm dc_irda_device_get_address +.Nd Get the address of the IrDA device. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/irda.h +.Ft "unsigned int" +.Fo dc_irda_device_get_address +.Fa "dc_irda_device_t *device" +.Fc +.Sh DESCRIPTION +Get the address of the IrDA device. Return value used for opening a IrDA device using +.Xr dc_irda_open 3 . +Requires a valid irda +.Fa device +of type +.Ft dc_irda_device_t +which can be retrieved using +.Xr dc_irda_iterator_new 3 . +.Sh RETURN VALUES +Returns the IrDA address of given IrDA +.Fa device +.Sh SEE ALSO +.Xr dc_irda_open 3 , +.Xr dc_irda_device_get_name 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_irda_device_get_name.3 b/doc/man/dc_irda_device_get_name.3 new file mode 100644 index 0000000..942ea6d --- /dev/null +++ b/doc/man/dc_irda_device_get_name.3 @@ -0,0 +1,58 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_IRDA_DEVICE_GET_NAME 3 +.Os +.Sh NAME +.Nm dc_irda_device_get_name +.Nd Get the address of the IrDA device. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/irda.h +.Ft "const char *" +.Fo dc_irda_device_get_name +.Fa "dc_irda_device_t *device" +.Fc +.Sh DESCRIPTION +Get the name of the IrDA device. Used for displaying. +Requires a valid irda +.Fa device +of type +.Ft dc_irda_device_t +which can be retrieved using +.Xr dc_irda_iterator_new 3 . +.Sh RETURN VALUES +Returns the IrDA name of given +.Fa irda_device +.Sh SEE ALSO +.Xr dc_irda_device_get_address 3 . +.Xr dc_irda_iterator_new 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_irda_iterator_new.3 b/doc/man/dc_irda_iterator_new.3 new file mode 100644 index 0000000..b24f73d --- /dev/null +++ b/doc/man/dc_irda_iterator_new.3 @@ -0,0 +1,102 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_IRDA_ITERATOR_NEW 3 +.Os +.Sh NAME +.Nm dc_irda_iterator_new +.Nd Create an iterator to enumerate the IrDA devices. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/irda.h +.Ft dc_status_t +.Fo dc_irda_iterator_new +.Fa "dc_iterator_t **iterator" +.Fa "dc_context_t *context" +.Fa "dc_descriptor_t *descriptor" +.Fc +.Sh DESCRIPTION +Iterates through the available IrDA devices which matches the given +.Fa descriptor . +Accepts a +.Fa context +opened with +.Xr dc_context_new 3 +and a +.Fa descriptor +usually found by searching through +.Xr dc_descriptor_iterator 3 . +.Pp +On returning +.Dv DC_STATUS_SUCCESS +the +.Fa iterator +will be set to an +.Ft dc_iterator_t +which can be used to iterate the available IrDA devices using +.Xr dc_iterator_next 3 . +.Pp +The value type of the iterator is of type +.Ft dc_irda_device_t . +This value can be used in functions to extract information about this specific IrDA device, namely +.Xr dc_irda_device_get_name 3 +and +.Xr dc_irda_device_get_address 3 . +When done the IrDA device needs to be freed with +.Xr dc_irda_device_free 3 . +.Pp +After iterating the +.Fa iterator +needs to be freed using +.Xr dc_iterator_free 3 . + +.Sh RETURN VALUES +Returns +.Dv DC_STATUS_SUCCESS +on success, or another +.Ft dc_status_t +code on failure. + +On +.Dv DC_STATUS_SUCCESS +the returned +.Fa iterator +needs to be freed when done using +.Xr dc_iterator_free 3 . +.Sh SEE ALSO +.Xr dc_context_new 3 , +.Xr dc_usbhid_iterator_new 3 , +.Xr dc_serial_iterator_new 3 , +.Xr dc_bluetooth_iterator_new 3 , +.Xr dc_irda_device_get_name 3 , +.Xr dc_irda_device_get_address 3 , +.Xr dc_irda_device_free 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_irda_open.3 b/doc/man/dc_irda_open.3 new file mode 100644 index 0000000..53d92df --- /dev/null +++ b/doc/man/dc_irda_open.3 @@ -0,0 +1,85 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_IRDA_OPEN 3 +.Os +.Sh NAME +.Nm dc_irda_open +.Nd Opens an iostream for a IrDA device +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/irda.h +.Ft dc_status_t +.Fo dc_irda_open +.Fa "dc_iostream_t **iostream" +.Fa "dc_context_t *context" +.Fa "unsigned int address" +.Fa "unsigned int lsap" +.Fc +.Sh DESCRIPTION +Opens an iostream for a IrDA (Infra Red) device. +Accepts a +.Fa context +opened with +.Xr dc_context_new 3 , +.Fa address +given through +.Xr dc_irda_iterator_new 3 +together with +.Xr dc_irda_device_get_address 3 +, the last argument +.Fa lsap +is a port number used during the communication. Currently only Uwatec computers use IrDA comminication and for those the +.Fa lsap +can be hardcoded to 1 +.Pp +Upon returning +.Dv DC_STATUS_SUCCESS , +the +.Fa iostream +pointer must be freed with +.Xr dc_iostream_close 3 . +.Sh RETURN VALUES +Returns +.Dv DC_STATUS_SUCCESS +on success or one of several error values on error. +On success, the +.Fa iostream +pointer is filled in with an open handle. +.Sh SEE ALSO +.Xr dc_context_new 3 , +.Xr dc_iostream_close 3 , +.Xr dc_serial_open 3 , +.Xr dc_usbhid_open 3 , +.Xr dc_bluetooth_open 3 , +.Xr dc_irda_iterator_new 3 , +.Xr dc_irda_device_get_address 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . \ No newline at end of file diff --git a/doc/man/dc_parser_get_field.3 b/doc/man/dc_parser_get_field.3 index 2b276a1..a4c33f2 100644 --- a/doc/man/dc_parser_get_field.3 +++ b/doc/man/dc_parser_get_field.3 @@ -149,7 +149,7 @@ the tank volume units as or .Dv DC_TANKVOLUME_METRIC ; .Va volume , -the tank volume in bar or zero if the tank is +the tank volume in litres or zero if the tank is .Dv DC_TANKVOLUME_NONE ; .Va workpressure , the work pressure in bar or zero if diff --git a/doc/man/dc_parser_samples_foreach.3 b/doc/man/dc_parser_samples_foreach.3 index 5a92011..5ac5554 100644 --- a/doc/man/dc_parser_samples_foreach.3 +++ b/doc/man/dc_parser_samples_foreach.3 @@ -126,7 +126,7 @@ Sets the .Fa rbt field. .It Dv DC_SAMPLE_HEARTBEAT -The diver's heartbeet in beats per minute. +The diver's heartbeat in beats per minute. Sets the .Fa heartbeat field. diff --git a/doc/man/dc_serial_device_free.3 b/doc/man/dc_serial_device_free.3 new file mode 100644 index 0000000..5ee78b5 --- /dev/null +++ b/doc/man/dc_serial_device_free.3 @@ -0,0 +1,52 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_SERIAL_DEVICE_FREE 3 +.Os +.Sh NAME +.Nm dc_serial_device_free +.Nd Destroy the serial device and free all resources. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/serial.h +.Ft void +.Fo dc_serial_device_free +.Fa "dc_serial_device_t *device" +.Fc +.Sh DESCRIPTION +Destroy the serial device and free all resources. +The serial +.Fa device +usually found by searching through +.Xr dc_serial_iterator_new 3 . +.Sh SEE ALSO +.Xr dc_serial_iterator_new 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_serial_device_get_name.3 b/doc/man/dc_serial_device_get_name.3 new file mode 100644 index 0000000..88c4e68 --- /dev/null +++ b/doc/man/dc_serial_device_get_name.3 @@ -0,0 +1,59 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_SERIAL_DEVICE_GET_NAME 3 +.Os +.Sh NAME +.Nm dc_serial_device_get_name +.Nd Get the device name of the serial device. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/serial.h +.Ft "const char *" +.Fo dc_serial_device_get_name +.Fa "dc_serial_device_t *device" +.Fc +.Sh DESCRIPTION +Get the device node of the serial device. Used when opening serial transport with +.Xr dc_serial_open 3 . +Requires a valid serial +.Fa device +of type +.Ft dc_serial_device_t +which can be retrieved using +.Xr dc_serial_iterator_new 3 . +.Sh RETURN VALUES +Returns the device name of given serial +.Fa device +.Sh SEE ALSO +.Xr dc_serial_open 3 , +.Xr dc_serial_iterator_new 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_serial_iterator_new.3 b/doc/man/dc_serial_iterator_new.3 new file mode 100644 index 0000000..91ad54c --- /dev/null +++ b/doc/man/dc_serial_iterator_new.3 @@ -0,0 +1,99 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_SERIAL_ITERATOR_NEW 3 +.Os +.Sh NAME +.Nm dc_serial_iterator_new +.Nd Create an iterator to enumerate the serial devices. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/serial.h +.Ft dc_status_t +.Fo dc_serial_iterator_new +.Fa "dc_iterator_t **iterator" +.Fa "dc_context_t *context" +.Fa "dc_descriptor_t *descriptor" +.Fc +.Sh DESCRIPTION +Iterates through the available serial devices matching the given +.Fa descriptor . +Accepts a +.Fa context +opened with +.Xr dc_context_new 3 +and a +.Fa descriptor +usually found by searching through +.Xr dc_descriptor_iterator 3 . +.Pp +On returning +.Dv DC_STATUS_SUCCESS +the +.Fa iterator +will be set to an +.Ft dc_iterator_t +which can be used to iterate the available serial devices using +.Xr dc_iterator_next 3 . +.Pp +The value type of the iterator is of type +.Ft dc_serial_device_t . +This value can be used in functions to extract information about this specific serial device, namely +.Xr dc_serial_device_get_name 3 +When done the serial device needs to be freed with +.Xr dc_serial_device_free 3 . +.Pp +After iterating the +.Fa iterator +needs to be freed using +.Xr dc_iterator_free 3 . + +.Sh RETURN VALUES +Returns +.Dv DC_STATUS_SUCCESS +on success, or another +.Ft dc_status_t +code on failure. + +On +.Dv DC_STATUS_SUCCESS +the returned +.Fa iterator +needs to be freed when done using +.Xr dc_iterator_free 3 . +.Sh SEE ALSO +.Xr dc_context_new 3 , +.Xr dc_usbhid_iterator_new 3 , +.Xr dc_irda_iterator_new 3 , +.Xr dc_bluetooth_iterator_new 3 , +.Xr dc_serial_device_get_name 3 , +.Xr dc_serial_device_free 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_serial_open.3 b/doc/man/dc_serial_open.3 new file mode 100644 index 0000000..df8547c --- /dev/null +++ b/doc/man/dc_serial_open.3 @@ -0,0 +1,80 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_SERIAL_OPEN 3 +.Os +.Sh NAME +.Nm dc_serial_open +.Nd Opens an iostream for a serial device +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/serial.h +.Ft dc_status_t +.Fo dc_serial_open +.Fa "dc_iostream_t **iostream" +.Fa "dc_context_t *context" +.Fa "const char *name" +.Fc +.Sh DESCRIPTION +Opens an iostream for a serial device. +Accepts a +.Fa context +opened with +.Xr dc_context_new 3 +and a +.Fa name +device name, usually found through +.Xr dc_serial_iterator_new 3 +with +.Xr dc_serial_device_get_name 3 . +.Pp +Upon returning +.Dv DC_STATUS_SUCCESS , +the +.Fa iostream +pointer must be freed with +.Xr dc_iostream_close 3 . +.Sh RETURN VALUES +Returns +.Dv DC_STATUS_SUCCESS +on success or one of several error values on error. +On success, the +.Fa iostream +pointer is filled in with an open handle. +.Sh SEE ALSO +.Xr dc_context_new 3 , +.Xr dc_iostream_close 3 , +.Xr dc_usbhid_open 3 , +.Xr dc_irda_open 3 , +.Xr dc_bluetooth_open 3 , +.Xr dc_serial_iterator_new 3 , +.Xr dc_serial_device_get_name 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_usbhid_device_free.3 b/doc/man/dc_usbhid_device_free.3 new file mode 100644 index 0000000..a4bb94a --- /dev/null +++ b/doc/man/dc_usbhid_device_free.3 @@ -0,0 +1,52 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_USBHID_DEVICE_FREE 3 +.Os +.Sh NAME +.Nm dc_usbhid_device_free +.Nd Destroy the USB HID device and free all resources. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/usbhid.h +.Ft void +.Fo dc_usbhid_device_free +.Fa "dc_usbhid_device_t *device" +.Fc +.Sh DESCRIPTION +Destroy the USB HID device and free all resources. +The usbhid +.Fa device +usually found by searching through +.Xr dc_usbhid_iterator_new 3 . +.Sh SEE ALSO +.Xr dc_usbhid_iterator_new 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_usbhid_device_get_pid.3 b/doc/man/dc_usbhid_device_get_pid.3 new file mode 100644 index 0000000..6a371c5 --- /dev/null +++ b/doc/man/dc_usbhid_device_get_pid.3 @@ -0,0 +1,58 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_USBHID_DEVICE_GET_PID 3 +.Os +.Sh NAME +.Nm dc_usbhid_device_get_pid +.Nd Get the product id (PID) of the USB HID device. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/usbhid.h +.Ft "unsigned int" +.Fo dc_usbhid_device_get_pid +.Fa "dc_usbhid_device_t *device" +.Fc +.Sh DESCRIPTION +Get the product id (PID) of the USB HID device. Used for displaying. +Requires a valid usbhid +.Fa device +of type +.Ft dc_usbhid_device_t +which can be retrieved using +.Xr dc_usbhid_iterator_new 3 . +.Sh RETURN VALUES +Returns the product id (PID) of given +.Fa usbhid_device +.Sh SEE ALSO +.Xr dc_usbhid_device_get_vid 3 , +.Xr dc_usbhid_iterator_new 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_usbhid_device_get_vid.3 b/doc/man/dc_usbhid_device_get_vid.3 new file mode 100644 index 0000000..e82ac53 --- /dev/null +++ b/doc/man/dc_usbhid_device_get_vid.3 @@ -0,0 +1,58 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_USBHID_DEVICE_GET_VID 3 +.Os +.Sh NAME +.Nm dc_usbhid_device_get_vid +.Nd Get the vendor id (VID) of the USB HID device. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/usbhid.h +.Ft "unsigned int" +.Fo dc_usbhid_device_get_vid +.Fa "dc_usbhid_device_t *device" +.Fc +.Sh DESCRIPTION +Get the vendor id (VID) of the USB HID device. Used for displaying. +Requires a valid usbhid +.Fa device +of type +.Ft dc_usbhid_device_t +which can be retrieved using +.Xr dc_usbhid_iterator_new 3 . +.Sh RETURN VALUES +Returns the vendor id (VID) of given usbhid +.Fa device +.Sh SEE ALSO +.Xr dc_usbhid_device_get_vid 3 , +.Xr dc_usbhid_iterator_new 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_usbhid_iterator_new.3 b/doc/man/dc_usbhid_iterator_new.3 new file mode 100644 index 0000000..0778d38 --- /dev/null +++ b/doc/man/dc_usbhid_iterator_new.3 @@ -0,0 +1,101 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_USBHID_ITERATOR_NEW 3 +.Os +.Sh NAME +.Nm dc_usbhid_iterator_new +.Nd Create an iterator to enumerate the USB HID devices. +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/usbhid.h +.Ft dc_status_t +.Fo dc_usbhid_iterator_new +.Fa "dc_iterator_t **iterator" +.Fa "dc_context_t *context" +.Fa "dc_descriptor_t *descriptor" +.Fc +.Sh DESCRIPTION +Iterates through the available USB HID devices matching the given +.Fa descriptor . +Accepts a +.Fa context +opened with +.Xr dc_context_new 3 +and a +.Fa descriptor +usually found by searching through +.Xr dc_descriptor_iterator 3 . +.Pp +On returning +.Dv DC_STATUS_SUCCESS +the +.Fa iterator +will be set to an +.Ft dc_iterator_t +which can be used to iterate the available USB HID devices using +.Xr dc_iterator_next 3 . +.Pp +The value type of the iterator is of type +.Ft dc_usbhid_device_t . +This value can be used in functions to extract information about this specific USB HID device, namely +.Xr dc_usbhid_device_get_pid 3 +and +.Xr dc_usbhid_device_get_vid 3 . +When done the USB HID device needs to be freed with +.Xr dc_usbhid_device_free 3 . +.Pp +After iterating the +.Fa iterator +needs to be freed using +.Xr dc_iterator_free 3 . + +.Sh RETURN VALUES +Returns +.Dv DC_STATUS_SUCCESS +on success, or another +.Ft dc_status_t +code on failure. + +On +.Dv DC_STATUS_SUCCESS +the returned +.Fa iterator +needs to be freed when done using +.Xr dc_iterator_free 3 . +.Sh SEE ALSO +.Xr dc_context_new 3 , +.Xr dc_bluetooth_iterator_new 3 , +.Xr dc_serial_iterator_new 3 , +.Xr dc_irda_iterator_new 3 , +.Xr dc_usbhid_device_get_pid 3 , +.Xr dc_usbhid_device_get_vid 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . diff --git a/doc/man/dc_usbhid_open.3 b/doc/man/dc_usbhid_open.3 new file mode 100644 index 0000000..e7dce39 --- /dev/null +++ b/doc/man/dc_usbhid_open.3 @@ -0,0 +1,77 @@ +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2020 Vincent Hagen +.\" +.\" 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 June 5, 2020 +.Dt DC_USBHID_OPEN 3 +.Os +.Sh NAME +.Nm dc_usbhid_open +.Nd Opens an iostream for a USB HID device +.Sh LIBRARY +.Lb libdivecomputer +.Sh SYNOPSIS +.In libdivecomputer/usbhid.h +.Ft dc_status_t +.Fo dc_usbhid_open +.Fa "dc_iostream_t **iostream" +.Fa "dc_context_t *context" +.Fa "dc_usbhid_device_t *device" +.Fc +.Sh DESCRIPTION +Opens an iostream for a USB HID device. +Accepts a +.Fa context +opened with +.Xr dc_context_new 3 +and a +.Fa device +usually found by searching through +.Xr dc_usbhid_iterator_new 3 . +.Pp +Upon returning +.Dv DC_STATUS_SUCCESS , +the +.Fa iostream +pointer must be freed with +.Xr dc_iostream_close 3 . +.Sh RETURN VALUES +Returns +.Dv DC_STATUS_SUCCESS +on success or one of several error values on error. +On success, the +.Fa iostream +pointer is filled in with an open handle. +.Sh SEE ALSO +.Xr dc_context_new 3 , +.Xr dc_usbhid_iterator_new 3 , +.Xr dc_iostream_close 3 , +.Xr dc_serial_open 3 , +.Xr dc_irda_open 3 , +.Xr dc_bluetooth_open 3 . +.Sh AUTHORS +The +.Lb libdivecomputer +library was written by +.An Jef Driesen , +.Mt jef@libdivecomputer.org . +.br +This manpage is written by +.An Vincent Hagen , +.Mt vinnie@script4web.nl . \ No newline at end of file diff --git a/doc/man/libdivecomputer.3 b/doc/man/libdivecomputer.3 index c85f140..4e1f601 100644 --- a/doc/man/libdivecomputer.3 +++ b/doc/man/libdivecomputer.3 @@ -41,9 +41,8 @@ these steps: .Bl -enum .It Create a new context with -.Xr dc_context_new 3 . -This supplies a parse context: logging, error handling, etc. -Override the values with +.Xr dc_context_new 3 +to initialize the library. Logging can be controlled with .Xr dc_context_set_logfunc 3 and .Xr dc_context_set_loglevel 3 . @@ -52,11 +51,28 @@ Find a descriptor for their dive computer by iterating through .Xr dc_descriptor_iterator 3 and searching by name, vendor, or product family. .It -Open the hardware device to which the dive computer is connected with -.Xr dc_device_open 3 , -then invoke +Find the transport to use for the communication. To determine the supported transports use +.Xr dc_descriptor_get_transports 3 . +.It +Find the hardware device corresponding to the connected dive computer by iterating through +.Xr dc_usbhid_iterator_new 3 , +.Xr dc_serial_iterator_new 3 , +.Xr dc_irda_iterator_new 3 +or +.Xr dc_bluetooth_iterator_new 3 . +.It +Open the transport communcations with +.Xr dc_usbhid_open 3 , +.Xr dc_serial_open 3 , +.Xr dc_irda_open 3 +or +.Xr dc_bluetooth_open 3 . +.It +Open a connection to the dive computer with +.Xr dc_device_open 3 . +Optionally use .Xr dc_device_set_events 3 , -.Xr dc_device_set_fingerprint 3 , +.Xr dc_device_set_fingerprint 3 and .Xr dc_device_set_cancel 3 to set the logging events, last-seen fingerprint, and cancel routine, @@ -71,8 +87,9 @@ and set the parsed data with .Xr dc_parser_set_data 3 . .It Get attributes of the parsed dive with -.Xr dc_parser_get_field 3 , -then iterate through the dive's samples (recorded data) with +.Xr dc_parser_get_field 3 . +.It +Iterate through the dive's samples (recorded data) with .Xr dc_parser_samples_foreach 3 . .El .Sh RETURN VALUES @@ -129,7 +146,10 @@ return .Dv DC_STATUS_SUCCESS . .El .Sh SEE ALSO -.Xr dc_buffer_new 3 +.Xr dc_context_new 3 , +.Xr dc_descriptor_iterator 3 +.Xr dc_device_open 3 +.Xr dc_parser_new 3 .Sh AUTHORS The .Lb libdivecomputer diff --git a/examples/common.c b/examples/common.c index 7930a70..d8b4d0d 100644 --- a/examples/common.c +++ b/examples/common.c @@ -90,9 +90,9 @@ static const backend_table_t g_backends[] = { {"idive", DC_FAMILY_DIVESYSTEM_IDIVE, 0x03}, {"cochran", DC_FAMILY_COCHRAN_COMMANDER, 0}, {"divecomputereu", DC_FAMILY_TECDIVING_DIVECOMPUTEREU, 0}, - {"descentmk1", DC_FAMILY_GARMIN, 0}, + {"descentmk1", DC_FAMILY_GARMIN, 0}, {"cosmiq", DC_FAMILY_DEEPBLU, 0}, - {"mclean", DC_FAMILY_MCLEAN_EXTREME, 0}, + {"mclean", DC_FAMILY_MCLEAN_EXTREME, 0}, }; static const transport_table_t g_transports[] = { diff --git a/include/libdivecomputer/common.h b/include/libdivecomputer/common.h index b0aa67f..d09cd47 100644 --- a/include/libdivecomputer/common.h +++ b/include/libdivecomputer/common.h @@ -108,12 +108,12 @@ typedef enum dc_family_t { DC_FAMILY_COCHRAN_COMMANDER = (14 << 16), /* Tecdiving */ DC_FAMILY_TECDIVING_DIVECOMPUTEREU = (15 << 16), - /* Garmin */ - DC_FAMILY_GARMIN = (16 << 16), - /* Deepblu */ - DC_FAMILY_DEEPBLU = (17 << 16), /* McLean */ - DC_FAMILY_MCLEAN_EXTREME = (18 << 16), + DC_FAMILY_MCLEAN_EXTREME = (16 << 16), + /* Garmin */ + DC_FAMILY_GARMIN = (17 << 16), + /* Deepblu */ + DC_FAMILY_DEEPBLU = (18 << 16), } dc_family_t; #ifdef __cplusplus diff --git a/msvc/libdivecomputer.vcproj b/msvc/libdivecomputer.vcproj index dcf3f49..daac0ef 100644 --- a/msvc/libdivecomputer.vcproj +++ b/msvc/libdivecomputer.vcproj @@ -350,6 +350,14 @@ RelativePath="..\src\mares_puck.c" > + + + + @@ -724,6 +732,10 @@ RelativePath="..\src\mares_puck.h" > + + diff --git a/src/descriptor.c b/src/descriptor.c index a212def..3cec2fe 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -50,7 +50,7 @@ static int dc_filter_mares (dc_transport_t transport, const void *userdata); static int dc_filter_divesystem (dc_transport_t transport, const void *userdata); static int dc_filter_oceanic (dc_transport_t transport, const void *userdata); static int dc_filter_deepblu (dc_transport_t transport, const void *userdata); -static int dc_filter_mclean(dc_transport_t transport, const void *userdata); +static int dc_filter_mclean (dc_transport_t transport, const void *userdata); static dc_status_t dc_descriptor_iterator_next (dc_iterator_t *iterator, void *item); @@ -384,7 +384,7 @@ static const dc_descriptor_t g_descriptors[] = { /* Deepblu */ {"Deepblu", "Cosmiq+", DC_FAMILY_DEEPBLU, 0, DC_TRANSPORT_BLE, dc_filter_deepblu}, /* McLean Extreme */ - { "McLean", "Extreme", DC_FAMILY_MCLEAN_EXTREME, 0, DC_TRANSPORT_BLUETOOTH, dc_filter_mclean }, + { "McLean", "Extreme", DC_FAMILY_MCLEAN_EXTREME, 0, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_mclean}, }; static int @@ -664,16 +664,15 @@ static int dc_filter_deepblu (dc_transport_t transport, const void *userdata) return 1; } -static int dc_filter_mclean(dc_transport_t transport, const void* userdata) +static int dc_filter_mclean(dc_transport_t transport, const void *userdata) { - static const char* const bluetooth[] = { + static const char * const bluetooth[] = { "Extreme", }; if (transport == DC_TRANSPORT_BLUETOOTH) { - return DC_FILTER_INTERNAL(userdata, bluetooth, 0, dc_match_name); - } - else if (transport == DC_TRANSPORT_SERIAL) { + return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_name); + } else if (transport == DC_TRANSPORT_SERIAL) { return DC_FILTER_INTERNAL(userdata, rfcomm, 1, dc_match_devname); } diff --git a/src/device.c b/src/device.c index 3167f4b..0a3d4e4 100644 --- a/src/device.c +++ b/src/device.c @@ -221,7 +221,7 @@ dc_device_open (dc_device_t **out, dc_context_t *context, dc_descriptor_t *descr rc = deepblu_device_open (&device, context, iostream); break; case DC_FAMILY_MCLEAN_EXTREME: - rc = mclean_extreme_device_open(&device, context, iostream); + rc = mclean_extreme_device_open (&device, context, iostream); break; default: return DC_STATUS_INVALIDARGS; diff --git a/src/hw_ostc_parser.c b/src/hw_ostc_parser.c index 0bb0804..83746e3 100644 --- a/src/hw_ostc_parser.c +++ b/src/hw_ostc_parser.c @@ -733,14 +733,6 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call else samplerate = data[36]; - // Get the salinity factor. - unsigned int salinity = data[layout->salinity]; - if (version == 0x23 || version == 0x24) - salinity += 100; - if (salinity < 100 || salinity > 104) - salinity = 100; - double hydrostatic = GRAVITY * salinity * 10.0; - // Get the number of sample descriptors. unsigned int nconfig = 0; if (version == 0x23 || version == 0x24) @@ -844,9 +836,9 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call if (callback) callback (DC_SAMPLE_CNS, sample, userdata); } - // Depth (mbar). + // Depth (1/100 m). unsigned int depth = array_uint16_le (data + offset); - sample.depth = (depth * BAR / 1000.0) / hydrostatic; + sample.depth = depth / 100.0; if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); offset += 2; @@ -996,12 +988,12 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call for (unsigned int i = 0; i < nconfig; ++i) { if (info[i].divisor && (nsamples % info[i].divisor) == 0) { if (length < info[i].size) { - // Due to a bug in the hwOS Tech firmware v3.03 to v3.07, and + // Due to a bug in the hwOS Tech firmware v3.03 to v3.08, and // the hwOS Sport firmware v10.57 to v10.63, the ppO2 divisor // is sometimes not correctly reset to zero when no ppO2 // samples are being recorded. if (info[i].type == PPO2 && parser->hwos && parser->model != OSTC4 && - ((firmware >= OSTC3FW(3,3) && firmware <= OSTC3FW(3,7)) || + ((firmware >= OSTC3FW(3,3) && firmware <= OSTC3FW(3,8)) || (firmware >= OSTC3FW(10,57) && firmware <= OSTC3FW(10,63)))) { WARNING (abstract->context, "Reset invalid ppO2 divisor to zero."); info[i].divisor = 0; diff --git a/src/mclean_extreme.c b/src/mclean_extreme.c index c3499a5..5c8060c 100644 --- a/src/mclean_extreme.c +++ b/src/mclean_extreme.c @@ -1,7 +1,7 @@ /* * libdivecomputer * - * Copyright (C) 2018 Jef Driesen + * Copyright (C) 2020 Jef Driesen, David Carron * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,7 +21,6 @@ #include // memcmp, memcpy #include // malloc, free -#include #include "mclean_extreme.h" #include "context-private.h" @@ -30,78 +29,40 @@ #define ISINSTANCE(device) dc_device_isinstance((device), &mclean_extreme_device_vtable) -#define MAXRETRIES 14 +#define MAXRETRIES 14 -#define STX 0x7E +#define STX 0x7E -#define CMD_COMPUTER 0xa0 // download computer configuration -#define CMD_SETCOMPUTER 0xa1 // upload computer configuration -#define CMD_DIVE 0xa3 // download specified dive configuration and samples -#define CMD_CLOSE 0xaa // close connexion and turn off bluetooth +#define CMD_SERIALNUMBER 0x91 +#define CMD_COMPUTER 0xA0 +#define CMD_SET_COMPUTER 0xA1 +#define CMD_DIVE 0xA3 +#define CMD_CLOSE 0xAA +#define CMD_SET_TIME 0xAC +#define CMD_FIRMWARE 0xAD -#define SZ_PACKET 512 // maximum packe payload length -#define SZ_SUMMARY 7 // size of the device fingerprint -#define SZ_CFG 0x002d // size of the common dive/computer header -#define SZ_COMPUTER 0x0097 // size of the computer state dump -#define SZ_DIVE 0x005e // size of the dive state dump -#define SZ_SAMPLE 0x0004 // size of the sample state dump +#define SZ_PACKET 512 +#define SZ_FINGERPRINT 7 +#define SZ_CFG 0x002D +#define SZ_COMPUTER (SZ_CFG + 0x6A) +#define SZ_HEADER (SZ_CFG + 0x31) +#define SZ_SAMPLE 0x0004 -// private device parsing functions ////////////////////////////////////////////////////////////////////////////////////////// +#define EPOCH 946684800 // 2000-01-01 00:00:00 UTC -static uint16_t uint16(const unsigned char* buffer, int addr) { return (buffer[0 + addr] << 0) | (buffer[1 + addr] << 8); } -static uint32_t uint32(const unsigned char* buffer, int addr) { return (uint16(buffer, addr) << 0) | (uint16(buffer, addr + 2) << 16); } - -static uint8_t device_format(const unsigned char* device) { return device[0x0000]; } -// static uint8_t device_gas_pO2(const unsigned char* device, int value) { return device[0x0001 + value * 2]; } -// static uint8_t device_gas_pHe(const unsigned char* device, int value) { return device[0x0001 + 1 + value * 2]; } -// static bool device_gas_enabled(const unsigned char* device, int value) { return (device[0x0011] & (1 << value)) != 0; } -// static uint8_t device_setpoint(const unsigned char* device, int value) { return device[0x0013 + value]; } -// static bool device_setpoint_enabled(const unsigned char* device, int value) { return (device[device, 0x0016] & (1 << value)) != 0; } -// static bool device_metric(unsigned char* device) { return device[0x0018] != 0; } -static uint16_t device_name(const unsigned char* device) { return uint16(device, 0x0019); } -// static uint16_t device_Vasc(const unsigned char* device) { return uint16(device, 0x001c); } -// static uint16_t device_Psurf(const unsigned char* device) { return uint16(device, 0x001e); } -// static uint8_t device_gfs_index(const unsigned char* device) { return device[0x0020]; } -// static uint8_t device_gflo(const unsigned char* device) { return device[0x0021]; } -// static uint8_t device_gfhi(const unsigned char* device) { return device[0x0022]; } -// static uint8_t device_density_index(const unsigned char* device) { return device[0x0023]; } -// static uint16_t device_ppN2_limit(const unsigned char* device) { return uint16(device, 0x0024); } -// static uint16_t device_ppO2_limit(const unsigned char* device) { return uint16(device, 0x0026); } -// static uint16_t device_ppO2_bottomlimit(const unsigned char* device) { return uint16(device, 0x0028); } -// static uint16_t device_density_limit(const unsigned char* device) { return uint16(device, 0x002a); } -// static uint8_t device_operatingmode(const unsigned char* device) { return device[0x002c]; } - -// static uint16_t device_inactive_timeout(const unsigned char* device) { return uint16(device, SZ_CFG + 0x0008); } -// static uint16_t device_dive_timeout(const unsigned char* device) { return uint16(device, SZ_CFG + 0x000a); } -// static uint16_t device_log_period(const unsigned char* device) { return device[SZ_CFG + 0x000c]; } -// static uint16_t device_log_timeout(const unsigned char* device) { return uint16(device, SZ_CFG + 0x000e); } -// static uint8_t device_brightness_timeout(const unsigned char* device) { return device[SZ_CFG + 0x0010]; } -// static uint8_t device_brightness(const unsigned char* device) { return device[SZ_CFG + 0x0012]; } -// static uint8_t device_colorscheme(const unsigned char* device) { return device[SZ_CFG + 0x0013]; } -// static uint8_t device_language(const unsigned char* device) { return device[SZ_CFG + 0x0014]; } -// static uint8_t device_batterytype(const unsigned char* device) { return device[SZ_CFG + 0x0015]; } -// static uint16_t device_batterytime(const unsigned char* device) { return uint16(device, SZ_CFG + 0x0014); } -// static uint8_t device_button_sensitivity(const unsigned char* device) { return device[SZ_CFG + 0x0016]; } -// static uint8_t device_orientation(const unsigned char* device) { return device[SZ_CFG + 0x0049]; } -// static const char* device_owner(const unsigned char* device) { return (const char*)& device[SZ_CFG + 0x004a]; } - -// private dive parsing functions ////////////////////////////////////////////////////////////////////////////////////////// - -static uint8_t dive_format(const unsigned char* dive) { return dive[0x0000]; } -static uint16_t dive_samples_cnt(const unsigned char* dive) { return uint16(dive, 0x005c); } - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#define NSTEPS 1000 +#define STEP(i,n) (NSTEPS * (i) / (n)) typedef struct mclean_extreme_device_t { dc_device_t base; - dc_iostream_t* iostream; - unsigned char fingerprint[SZ_SUMMARY]; - uint8_t data[SZ_COMPUTER]; + dc_iostream_t *iostream; + unsigned char fingerprint[SZ_FINGERPRINT]; } mclean_extreme_device_t; -static dc_status_t mclean_extreme_device_set_fingerprint(dc_device_t* abstract, const unsigned char data[], unsigned int size); -static dc_status_t mclean_extreme_device_foreach(dc_device_t* abstract, dc_dive_callback_t callback, void* userdata); -static dc_status_t mclean_extreme_device_close(dc_device_t* abstract); +static dc_status_t mclean_extreme_device_set_fingerprint(dc_device_t *abstract, const unsigned char data[], unsigned int size); +static dc_status_t mclean_extreme_device_timesync(dc_device_t *abstract, const dc_datetime_t *datetime); +static dc_status_t mclean_extreme_device_foreach(dc_device_t *abstract, dc_dive_callback_t callback, void *userdata); +static dc_status_t mclean_extreme_device_close(dc_device_t *abstract); static const dc_device_vtable_t mclean_extreme_device_vtable = { sizeof(mclean_extreme_device_t), @@ -111,10 +72,23 @@ static const dc_device_vtable_t mclean_extreme_device_vtable = { NULL, /* write */ NULL, /* dump */ mclean_extreme_device_foreach, /* foreach */ - NULL, /* timesync */ + mclean_extreme_device_timesync, /* timesync */ mclean_extreme_device_close, /* close */ }; +static unsigned int +hashcode (const unsigned char data[], size_t size) +{ + unsigned int result = 0; + + for (size_t i = 0; i < size; ++i) { + result *= 31; + result += data[i]; + } + + return result; +} + static unsigned short checksum_crc(const unsigned char data[], unsigned int size, unsigned short init) { @@ -124,8 +98,7 @@ checksum_crc(const unsigned char data[], unsigned int size, unsigned short init) if (crc & 0x8000) { crc <<= 1; crc ^= 0x1021; - } - else { + } else { crc <<= 1; } } @@ -134,10 +107,10 @@ checksum_crc(const unsigned char data[], unsigned int size, unsigned short init) } static dc_status_t -mclean_extreme_send(mclean_extreme_device_t* device, unsigned char cmd, const unsigned char data[], size_t size) +mclean_extreme_send(mclean_extreme_device_t *device, unsigned char cmd, const unsigned char data[], size_t size) { dc_status_t status = DC_STATUS_SUCCESS; - dc_device_t* abstract = (dc_device_t*)device; + dc_device_t *abstract = (dc_device_t *)device; unsigned short crc = 0; if (device_is_cancelled(abstract)) @@ -179,10 +152,10 @@ mclean_extreme_send(mclean_extreme_device_t* device, unsigned char cmd, const un } static dc_status_t -mclean_extreme_receive(mclean_extreme_device_t* device, unsigned char rsp, unsigned char data[], size_t max_size, size_t* actual_size) +mclean_extreme_receive(mclean_extreme_device_t *device, unsigned char rsp, unsigned char data[], size_t size, size_t *actual) { dc_status_t status = DC_STATUS_SUCCESS; - dc_device_t* abstract = (dc_device_t*)device; + dc_device_t *abstract = (dc_device_t *)device; unsigned char header[7]; unsigned int nretries = 0; @@ -236,8 +209,8 @@ mclean_extreme_receive(mclean_extreme_device_t* device, unsigned char rsp, unsig // Verify the length. unsigned int length = array_uint32_le(header + 2); - if (length > max_size) { - ERROR(abstract->context, "Unexpected packet length (%u for %zu).", length, max_size); + if (length > size) { + ERROR(abstract->context, "Unexpected packet length (%u).", length); return DC_STATUS_PROTOCOL; } @@ -285,25 +258,145 @@ mclean_extreme_receive(mclean_extreme_device_t* device, unsigned char rsp, unsig return DC_STATUS_PROTOCOL; } - if (actual_size != NULL) { + if (actual == NULL) { + // Verify the actual length. + if (length != size) { + ERROR (abstract->context, "Unexpected packet length (%u).", length); + return DC_STATUS_PROTOCOL; + } + } else { // Return the actual length. - *actual_size = length; + *actual = length; + } + + return DC_STATUS_SUCCESS; +} + +static dc_status_t +mclean_extreme_transfer(mclean_extreme_device_t *device, unsigned char cmd, const unsigned char data[], size_t size, unsigned char answer[], size_t asize, size_t *actual) +{ + dc_status_t status = DC_STATUS_SUCCESS; + + // Send the command + status = mclean_extreme_send(device, cmd, data, size); + if (status != DC_STATUS_SUCCESS) { + return status; + } + + // Receive the answer + if (asize) { + status = mclean_extreme_receive(device, cmd, answer, asize, actual); + if (status != DC_STATUS_SUCCESS) { + return status; + } + } + + return DC_STATUS_SUCCESS; +} + +static dc_status_t +mclean_extreme_readdive (dc_device_t *abstract, dc_event_progress_t *progress, unsigned int idx, dc_buffer_t *buffer) +{ + dc_status_t status = DC_STATUS_SUCCESS; + mclean_extreme_device_t *device = (mclean_extreme_device_t *) abstract; + + // Erase the buffer. + dc_buffer_clear (buffer); + + // Encode the logbook ID. + unsigned char id[] = { + (idx ) & 0xFF, + (idx >> 8) & 0xFF, + }; + + // Update and emit a progress event. + unsigned int initial = 0; + if (progress) { + initial = progress->current; + device_event_emit (abstract, DC_EVENT_PROGRESS, progress); + } + + // Request the dive. + status = mclean_extreme_send (device, CMD_DIVE, id, sizeof(id)); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to send the dive command."); + return status; + } + + // Read the dive header. + unsigned char header[SZ_HEADER]; + status = mclean_extreme_receive (device, CMD_DIVE, header, sizeof(header), NULL); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to receive the dive header."); + return status; + } + + // Verify the format version. + unsigned int format = header[0x0000]; + if (format != 0) { + ERROR(abstract->context, "Unrecognised dive format."); + return DC_STATUS_DATAFORMAT; + } + + // Get the number of samples. + unsigned int nsamples = array_uint16_le (header + 0x005C); + + // Calculate the total size. + unsigned int size = sizeof(header) + nsamples * SZ_SAMPLE; + + // Update and emit a progress event. + if (progress) { + progress->current = initial + STEP(sizeof(header), size); + device_event_emit (abstract, DC_EVENT_PROGRESS, progress); + } + + // Allocate memory for the dive. + if (!dc_buffer_resize (buffer, size)) { + ERROR (abstract->context, "Insufficient buffer space available."); + return DC_STATUS_NOMEMORY; + } + + // Cache the pointer. + unsigned char *data = dc_buffer_get_data(buffer); + + // Append the header. + memcpy (data, header, sizeof(header)); + + unsigned int nbytes = sizeof(header); + while (nbytes < size) { + // Get the maximum packet size. + size_t len = size - nbytes; + + // Read the dive samples. + status = mclean_extreme_receive (device, CMD_DIVE, data + nbytes, len, &len); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to receive the dive samples."); + return status; + } + + nbytes += len; + + // Update and emit a progress event. + if (progress) { + progress->current = initial + STEP(nbytes, size); + device_event_emit (abstract, DC_EVENT_PROGRESS, progress); + } } return DC_STATUS_SUCCESS; } dc_status_t -mclean_extreme_device_open(dc_device_t** out, dc_context_t* context, dc_iostream_t* iostream) +mclean_extreme_device_open(dc_device_t **out, dc_context_t *context, dc_iostream_t *iostream) { dc_status_t status = DC_STATUS_SUCCESS; - mclean_extreme_device_t* device = NULL; + mclean_extreme_device_t *device = NULL; if (out == NULL) return DC_STATUS_INVALIDARGS; // Allocate memory. - device = (mclean_extreme_device_t*)dc_device_allocate(context, &mclean_extreme_device_vtable); + device = (mclean_extreme_device_t *)dc_device_allocate(context, &mclean_extreme_device_vtable); if (device == NULL) { ERROR(context, "Failed to allocate memory."); return DC_STATUS_NOMEMORY; @@ -327,40 +420,24 @@ mclean_extreme_device_open(dc_device_t** out, dc_context_t* context, dc_iostream goto error_free; } - // Send the init command. - status = mclean_extreme_send(device, CMD_COMPUTER, NULL, 0); - if (status != DC_STATUS_SUCCESS) { - ERROR(context, "Failed to send the init command."); - goto error_free; - } + // Make sure everything is in a sane state. + dc_iostream_sleep (device->iostream, 100); + dc_iostream_purge (device->iostream, DC_DIRECTION_ALL); - // Read the device info. - status = mclean_extreme_receive(device, CMD_COMPUTER, device->data, sizeof(device->data), NULL); - if (status != DC_STATUS_SUCCESS) { - ERROR(context, "Failed to receive the device info."); - goto error_free; - } - - if (device_format(device->data) != 0) { /* bad device format */ - status = DC_STATUS_DATAFORMAT; - ERROR(context, "Unsupported device format."); - goto error_free; - } - - *out = (dc_device_t*)device; + *out = (dc_device_t *)device; return DC_STATUS_SUCCESS; error_free: - dc_device_deallocate((dc_device_t*)device); + dc_device_deallocate((dc_device_t *)device); return status; } static dc_status_t -mclean_extreme_device_close(dc_device_t* abstract) +mclean_extreme_device_close(dc_device_t *abstract) { dc_status_t status = DC_STATUS_SUCCESS; - mclean_extreme_device_t* device = (mclean_extreme_device_t*)abstract; + mclean_extreme_device_t *device = (mclean_extreme_device_t *)abstract; status = mclean_extreme_send(device, CMD_CLOSE, NULL, 0); if (status != DC_STATUS_SUCCESS) { @@ -372,125 +449,147 @@ mclean_extreme_device_close(dc_device_t* abstract) } static dc_status_t -mclean_extreme_device_set_fingerprint(dc_device_t* abstract, const unsigned char data[], unsigned int size) +mclean_extreme_device_set_fingerprint(dc_device_t *abstract, const unsigned char data[], unsigned int size) { - mclean_extreme_device_t* device = (mclean_extreme_device_t*)abstract; + mclean_extreme_device_t *device = (mclean_extreme_device_t *)abstract; - if (size && size != sizeof(device->fingerprint)) + if (size && size != sizeof(device->fingerprint)) { return DC_STATUS_INVALIDARGS; + } - if (size) + if (size) { memcpy(device->fingerprint, data, sizeof(device->fingerprint)); - else + } else { memset(device->fingerprint, 0, sizeof(device->fingerprint)); + } return DC_STATUS_SUCCESS; } static dc_status_t -mclean_extreme_device_readsamples(dc_device_t* abstract, uint8_t* dive) +mclean_extreme_device_timesync(dc_device_t *abstract, const dc_datetime_t *datetime) { - dc_status_t status = DC_STATUS_SUCCESS; - mclean_extreme_device_t* device = (mclean_extreme_device_t*)abstract; + mclean_extreme_device_t *device = (mclean_extreme_device_t *)abstract; - int samples_cnt = (dive[0x005c] << 0) + (dive[0x005d] << 8); // number of samples to follow - dive = &dive[SZ_DIVE]; + if (datetime == NULL) { + ERROR(abstract->context, "Invalid parameter specified."); + return DC_STATUS_INVALIDARGS; + } - while (samples_cnt != 0) { - unsigned char data[SZ_PACKET]; // buffer for read packet data - size_t length; // buffer for read packet length + // Get the UTC timestamp. + dc_ticks_t ticks = dc_datetime_mktime(datetime); + if (ticks == -1 || ticks < EPOCH || ticks - EPOCH > 0xFFFFFFFF) { + ERROR (abstract->context, "Invalid date/time value specified."); + return DC_STATUS_INVALIDARGS; + } - status = mclean_extreme_receive(device, CMD_DIVE, data, SZ_PACKET, &length); - if (status != DC_STATUS_SUCCESS) { - ERROR(abstract->context, "Failed to receive dive samples."); - break; - } + // Adjust the epoch. + unsigned int timestamp = ticks - EPOCH; - int packet_cnt = length / SZ_SAMPLE; // number of samples in the packet - if (packet_cnt > samples_cnt) { /* too many samples received */ - status = DC_STATUS_DATAFORMAT; - ERROR(abstract->context, "Too many dive samples received."); - break; - } - if (length != packet_cnt * SZ_SAMPLE) { /* not an integer number of samples */ - status = DC_STATUS_DATAFORMAT; - ERROR(abstract->context, "Partial samples received."); - break; - } - - memcpy(dive, data, packet_cnt * SZ_SAMPLE); // append samples to dive buffer - - dive = &dive[packet_cnt * SZ_SAMPLE]; // move buffer write cursor - samples_cnt -= packet_cnt; + // Send the command. + const unsigned char cmd[] = { + (timestamp ) & 0xFF, + (timestamp >> 8) & 0xFF, + (timestamp >> 16) & 0xFF, + (timestamp >> 24) & 0xFF + }; + dc_status_t status = mclean_extreme_send(device, CMD_SET_TIME, cmd, sizeof(cmd)); + if (status != DC_STATUS_SUCCESS) { + ERROR(abstract->context, "Failed to send the set time command."); + return status; } return status; } static dc_status_t -mclean_extreme_device_foreach(dc_device_t* abstract, dc_dive_callback_t callback, void* userdata) +mclean_extreme_device_foreach(dc_device_t *abstract, dc_dive_callback_t callback, void *userdata) { dc_status_t status = DC_STATUS_SUCCESS; - mclean_extreme_device_t* device = (mclean_extreme_device_t*)abstract; + mclean_extreme_device_t *device = (mclean_extreme_device_t *)abstract; + // Enable progress notifications. dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER; - device_event_emit(abstract, DC_EVENT_PROGRESS, &progress); + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); - int dives_cnt = device_name(device->data); - - progress.current = 0; - progress.maximum = dives_cnt; - device_event_emit(abstract, DC_EVENT_PROGRESS, &progress); - - for (int i = dives_cnt - 1; i >= 0; --i) { - unsigned char data[512]; // buffer for read packet data - size_t length; // buffer for read packet length - - unsigned char id[] = { (unsigned char)i, (unsigned char)(i >> 8) }; // payload for CMD_DIVE request - - status = mclean_extreme_send(device, CMD_DIVE, id, sizeof(id)); - if (status != DC_STATUS_SUCCESS) { - ERROR(abstract->context, "Failed to send the get dive command."); - break; - } - - status = mclean_extreme_receive(device, CMD_DIVE, data, 512, &length); - if (status != DC_STATUS_SUCCESS) { - ERROR(abstract->context, "Failed to receive dive header."); - break; - } - - if (dive_format(data) != 0) { /* can't understand the format */ - INFO(abstract->context, "Skipping unsupported dive format"); - break; - } - - int cnt_samples = dive_samples_cnt(data); // number of samples to follow - size_t size = SZ_DIVE + cnt_samples * SZ_SAMPLE; // total buffer size required for this dive - uint8_t* dive = (uint8_t *)malloc(size); // buffer for this dive - - if (dive == NULL) { - status = DC_STATUS_NOMEMORY; - break; - } - - memcpy(dive, data, SZ_DIVE); // copy data to dive buffer - status = mclean_extreme_device_readsamples(abstract, dive); // append samples to buffer - - if (status != DC_STATUS_SUCCESS) { /* failed to read dive samples */ - free(dive); // cleanup - break; // stop downloading - } - - if (callback && !callback(dive, size, dive, sizeof(device->fingerprint), userdata)) { /* cancelled by callback */ - free(dive); // cleanup - break; // stop downloading - } - - free(dive); - progress.current = dives_cnt - 1 - i; - device_event_emit(abstract, DC_EVENT_PROGRESS, &progress); + // Read the firmware version. + unsigned char firmware[4] = {0}; + status = mclean_extreme_transfer(device, CMD_FIRMWARE, NULL, 0, firmware, sizeof(firmware), NULL); + if (status != DC_STATUS_SUCCESS) { + ERROR(abstract->context, "Failed to read the firmware version."); + return status; } + // Read the serial number. + size_t serial_len = 0; + unsigned char serial[SZ_PACKET] = {0}; + status = mclean_extreme_transfer(device, CMD_SERIALNUMBER, NULL, 0, serial, sizeof(serial), &serial_len); + if (status != DC_STATUS_SUCCESS) { + ERROR(abstract->context, "Failed to read serial number."); + return status; + } + + // Emit a device info event. + dc_event_devinfo_t devinfo; + devinfo.model = 0; + devinfo.firmware = array_uint32_le (firmware); + devinfo.serial = hashcode (serial, serial_len); + device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo); + + // Read the computer configuration. + unsigned char computer[SZ_COMPUTER]; + status = mclean_extreme_transfer(device, CMD_COMPUTER, NULL, 0, computer, sizeof(computer), NULL); + if (status != DC_STATUS_SUCCESS) { + ERROR(abstract->context, "Failed to read the computer configuration."); + return status; + } + + // Verify the format version. + unsigned int format = computer[0x0000]; + if (format != 0) { + ERROR(abstract->context, "Unsupported device format."); + return DC_STATUS_DATAFORMAT; + } + + // Get the number of dives. + unsigned int ndives = array_uint16_le(computer + 0x0019); + + // Update and emit a progress event. + progress.current = 1 * NSTEPS; + progress.maximum = (ndives + 1) * NSTEPS; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + + // Allocate a memory buffer for a single dive. + dc_buffer_t *buffer = dc_buffer_new(0); + if (buffer == NULL) { + status = DC_STATUS_NOMEMORY; + goto error_exit; + } + + for (unsigned int i = 0; i < ndives; ++i) { + // Download in reverse order (newest first). + unsigned int idx = ndives - 1 - i; + + // Read the dive. + status = mclean_extreme_readdive (abstract, &progress, idx, buffer); + if (status != DC_STATUS_SUCCESS) { + goto error_buffer_free; + } + + // Cache the pointer. + unsigned char *data = dc_buffer_get_data(buffer); + unsigned int size = dc_buffer_get_size(buffer); + + if (memcmp(data, device->fingerprint, sizeof(device->fingerprint)) == 0) + break; + + if (callback && !callback (data, size, data, sizeof(device->fingerprint), userdata)) { + break; + } + } + +error_buffer_free: + dc_buffer_free (buffer); +error_exit: return status; } diff --git a/src/mclean_extreme.h b/src/mclean_extreme.h index 883061f..c388bd4 100644 --- a/src/mclean_extreme.h +++ b/src/mclean_extreme.h @@ -1,7 +1,7 @@ /* * libdivecomputer * - * Copyright (C) 2018 Jef Driesen + * Copyright (C) 2020 Jef Driesen, David Carron * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/mclean_extreme_parser.c b/src/mclean_extreme_parser.c index d8ff492..e696ee8 100644 --- a/src/mclean_extreme_parser.c +++ b/src/mclean_extreme_parser.c @@ -1,7 +1,7 @@ /* * libdivecomputer * - * Copyright (C) 2018 Jef Driesen + * Copyright (C) 2020 Jef Driesen, David Carron * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,8 +21,6 @@ #include #include -#include -#include #include "mclean_extreme.h" #include "context-private.h" @@ -31,76 +29,37 @@ #define ISINSTANCE(parser) dc_device_isinstance((parser), &mclean_extreme_parser_vtable) -#define SZ_CFG 0x002d // size of the common dive/computer header -#define SZ_COMPUTER 0x006a // size of the computer state dump -#define SZ_DIVE 0x005e // size of the dive state dump -#define SZ_SAMPLE 0x0004 // size of the sample state dump +#define SZ_CFG 0x002D +#define SZ_COMPUTER (SZ_CFG + 0x6A) +#define SZ_HEADER (SZ_CFG + 0x31) +#define SZ_SAMPLE 0x0004 -// private dive parsing functions ////////////////////////////////////////////////////////////////////////////////////////// +#define EPOCH 946684800 // 2000-01-01 00:00:00 UTC -static uint16_t uint16(const unsigned char* buffer, int addr) { return (buffer[0 + addr] << 0) | (buffer[1 + addr] << 8); } -static uint32_t uint32(const unsigned char* buffer, int addr) { return (buffer[0 + addr] << 0) | (buffer[1 + addr] << 8) | (buffer[2 + addr] << 16) | (buffer[3 + addr] << 24); } +#define REC 0 +#define TEC 1 +#define CCR 2 +#define GAUGE 3 -static uint8_t dive_format(const unsigned char* dive) { return dive[0x0000]; } -static uint8_t dive_gas_pO2(const unsigned char* dive, int value) { return dive[0x0001 + value * 2]; } -static uint8_t dive_gas_pHe(const unsigned char* dive, int value) { return dive[0x0001 + 1 + value * 2]; } -// static bool dive_gas_enabled(const unsigned char* dive, int value) { return (dive[0x0011] & (1 << value)) != 0; } -static uint8_t dive_setpoint(const unsigned char* dive, int value) { return dive[0x0013 + value]; } -// static bool dive_setpoint_enabled(const unsigned char* dive, int value) { return (dive[dive, 0x0016] & (1 << value)) != 0; } -// static bool dive_metric(const unsigned char* dive) { return dive[0x0018] != 0; } -// static uint16_t dive_name(const unsigned char* dive) { return uint16(dive, 0x0019); } -// static uint16_t dive_Vasc(const unsigned char* dive) { return uint16(dive, 0x001c); } -static uint16_t dive_Psurf(const unsigned char* dive) { return uint16(dive, 0x001e); } -// static uint8_t dive_gfs_index(const unsigned char* dive) { return dive[0x0020]; } -// static uint8_t dive_gflo(const unsigned char* dive) { return dive[0x0021]; } -// static uint8_t dive_gfhi(const unsigned char* dive) { return dive[0x0022]; } -static uint8_t dive_density_index(const unsigned char* dive) { return dive[0x0023]; } -// static uint16_t dive_ppN2_limit(const unsigned char* dive) { return uint16(dive, 0x0024); } -// static uint16_t dive_ppO2_limit(const unsigned char* dive) { return uint16(dive, 0x0026); } -// static uint16_t dive_ppO2_bottomlimit(const unsigned char* dive) { return uint16(dive, 0x0028); } -// static uint16_t dive_density_limit(const unsigned char* dive) { return uint16(dive, 0x002a); } -static uint8_t dive_operatingmode(const unsigned char* dive) { return dive[0x002c]; } +#define INVALID 0xFFFFFFFF -static uint32_t dive_logstart(const unsigned char* dive) { return uint32(dive, SZ_CFG + 0x0000); } -static uint32_t dive_divestart(const unsigned char* dive) { return uint32(dive, SZ_CFG + 0x0004); } -static uint32_t dive_diveend(const unsigned char* dive) { return uint32(dive, SZ_CFG + 0x0008); } -static uint32_t dive_logend(const unsigned char* dive) { return uint32(dive, SZ_CFG + 0x000c); } -static uint8_t dive_temp_min(const unsigned char* dive) { return dive[SZ_CFG + 0x0010]; } -static uint8_t dive_temp_max(const unsigned char* dive) { return dive[SZ_CFG + 0x0011]; } -// static uint16_t dive_pO2_min(const unsigned char* dive) { return uint16(dive, SZ_CFG + 0x0012); } -// static uint16_t dive_pO2_max(const unsigned char* dive) { return uint16(dive, SZ_CFG + 0x0014); } -static uint16_t dive_Pmax(const unsigned char* dive) { return uint16(dive, SZ_CFG + 0x0016); } -static uint16_t dive_Pav(const unsigned char* dive) { return uint16(dive, SZ_CFG + 0x0018); } -// static uint32_t ISS(const unsigned char* dive) { return uint16(dive, SZ_CFG + 0x001a); } -// static uint16_t CNS_start(const unsigned char* dive) { return uint16(dive, SZ_CFG + 0x001e); } -// static uint16_t CNS_max(const unsigned char* dive) { return uint16(dive, SZ_CFG + 0x0020); } -// static uint16_t OTU(const unsigned char* dive) { return uint16(dive, SZ_CFG + 0x0022); } -// static uint16_t tndl(const unsigned char* dive) { return uint16(dive, SZ_CFG + 0x0024); } -// static uint32_t tdeco(const unsigned char* dive) { return uint32(dive, SZ_CFG + 0x0026); } -// static uint8_t ndeco(const unsigned char* dive) { return dive[SZ_CFG + 0x002a]; } -// static uint32_t tdesat(const unsigned char* dive) { return uint32(dive, SZ_CFG + 0x002b); } -static uint16_t dive_samples_cnt(const unsigned char* dive) { return uint16(dive, 0x005c); } - -// private sample parsing functions ////////////////////////////////////////////////////////////////////////////////////////// - -static uint16_t sample_depth(const unsigned char* dive, int n) { return uint16(dive, SZ_DIVE + n * SZ_SAMPLE + 0); } -static uint8_t sample_temperature(const unsigned char* dive, int n) { return dive[SZ_DIVE + n * SZ_SAMPLE + 2]; } -static bool sample_ccr(const unsigned char* dive, int n) { return dive[SZ_DIVE + n * SZ_SAMPLE + 3] & 0b10000000; } -static uint8_t sample_sp_index(const unsigned char* dive, int n) { return (dive[SZ_DIVE + n * SZ_SAMPLE + 3] & 0b01100000) >> 5; } -static uint8_t sample_gas_index(const unsigned char* dive, int n) { return (dive[SZ_DIVE + n * SZ_SAMPLE + 3] & 0b00011100) >> 2; } - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#define NGASMIXES 8 typedef struct mclean_extreme_parser_t mclean_extreme_parser_t; struct mclean_extreme_parser_t { dc_parser_t base; + + // Cached fields. + unsigned int cached; + unsigned int 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_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_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_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 const dc_parser_vtable_t mclean_extreme_parser_vtable = { sizeof(mclean_extreme_parser_t), @@ -113,121 +72,154 @@ static const dc_parser_vtable_t mclean_extreme_parser_vtable = { }; dc_status_t -mclean_extreme_parser_create(dc_parser_t** out, dc_context_t* context) +mclean_extreme_parser_create(dc_parser_t **out, dc_context_t *context) { - mclean_extreme_parser_t* parser = NULL; + mclean_extreme_parser_t *parser = NULL; - if (out == NULL) + if (out == NULL) { return DC_STATUS_INVALIDARGS; + } // Allocate memory. - parser = (mclean_extreme_parser_t*)dc_parser_allocate(context, &mclean_extreme_parser_vtable); + parser = (mclean_extreme_parser_t *)dc_parser_allocate(context, &mclean_extreme_parser_vtable); if (parser == NULL) { ERROR(context, "Failed to allocate memory."); return DC_STATUS_NOMEMORY; } - *out = (dc_parser_t*)parser; + // Set the default values. + parser->cached = 0; + parser->ngasmixes = 0; + for (unsigned int i = 0; i < NGASMIXES; ++i) { + parser->gasmix[i] = INVALID; + } + + *out = (dc_parser_t *)parser; 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_set_data(dc_parser_t *abstract, const unsigned char *data, unsigned int size) { - dc_status_t status = DC_STATUS_SUCCESS; + mclean_extreme_parser_t *parser = (mclean_extreme_parser_t *)abstract; - if (dive_format(data) != 0) { - status = DC_STATUS_DATAFORMAT; - ERROR(abstract->context, "Unsupported dive format."); + // Reset the cache. + parser->cached = 0; + parser->ngasmixes = 0; + for (unsigned int i = 0; i < NGASMIXES; ++i) { + parser->gasmix[i] = INVALID; } - const int samples_cnt = dive_samples_cnt(data); + return DC_STATUS_SUCCESS; +} - if (size != SZ_DIVE + samples_cnt * SZ_SAMPLE) { - ERROR(abstract->context, "Corrupt dive in memory."); +static dc_status_t +mclean_extreme_parser_get_datetime(dc_parser_t *abstract, dc_datetime_t *datetime) +{ + if (abstract->size < SZ_HEADER) { + ERROR(abstract->context, "Corrupt dive data"); return DC_STATUS_DATAFORMAT; } + unsigned int timestamp = array_uint32_le(abstract->data + SZ_CFG + 0x0000); + dc_ticks_t ticks = (dc_ticks_t) timestamp + EPOCH; + + if (!dc_datetime_gmtime (datetime, ticks)) + return DC_STATUS_DATAFORMAT; + + datetime->timezone = DC_TIMEZONE_NONE; + return DC_STATUS_SUCCESS; } static dc_status_t -mclean_extreme_parser_get_datetime(dc_parser_t* abstract, dc_datetime_t* datetime) +mclean_extreme_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value) { - if (datetime) { - const unsigned char* dive = abstract->data; - dc_ticks_t dc_ticks = 946684800 + dive_logstart(dive); // raw times are offsets for 1/1/2000 + mclean_extreme_parser_t *parser = (mclean_extreme_parser_t *)abstract; - dc_datetime_gmtime(datetime, dc_ticks); + if (abstract->size < SZ_HEADER) { + ERROR(abstract->context, "Corrupt dive data"); + return DC_STATUS_DATAFORMAT; } - return DC_STATUS_SUCCESS; -} + if (!parser->cached) { + dc_status_t rc = mclean_extreme_parser_samples_foreach (abstract, NULL, NULL); + if (rc != DC_STATUS_SUCCESS) + return rc; + } -static dc_status_t -mclean_extreme_parser_get_field(dc_parser_t* abstract, dc_field_type_t type, unsigned int flags, void* value) -{ - static const double densities[] = { 1.000, 1.020, 1.030 }; - static const dc_divemode_t divemodes[] = { DC_DIVEMODE_OC, DC_DIVEMODE_OC, DC_DIVEMODE_CCR, DC_DIVEMODE_GAUGE }; + dc_gasmix_t *gasmix = (dc_gasmix_t *)value; + dc_salinity_t *salinity = (dc_salinity_t *)value; - const unsigned char* dive = abstract->data; - dc_gasmix_t* gasmix = (dc_gasmix_t*)value; + const unsigned int psurf = array_uint16_le(abstract->data + 0x001E); + const unsigned int density_index = abstract->data[0x0023]; + double density = 0; + + switch (density_index) { + case 0: + density = 1.000; + break; + case 1: + density = 1.020; + break; + case 2: + density = 1.030; + break; + default: + ERROR(abstract->context, "Corrupt density index in dive data"); + return DC_STATUS_DATAFORMAT; + } if (value) { switch (type) { case DC_FIELD_DIVETIME: - *((unsigned int*)value) = dive_logend(dive) - dive_logstart(dive); + *((unsigned int *)value) = array_uint32_le(abstract->data + SZ_CFG + 0x000C) - array_uint32_le(abstract->data + SZ_CFG + 0x0000); break; - case DC_FIELD_MAXDEPTH: - *((double*)value) = 0.01 * (dive_Pmax(dive) - dive_Psurf(dive)) / densities[dive_density_index(dive)]; + *((double *)value) = 0.01 * (array_uint16_le(abstract->data + SZ_CFG + 0x0016) - psurf) / density; break; - case DC_FIELD_AVGDEPTH: - *((double*)value) = 0.01 * (dive_Pav(dive) - dive_Psurf(dive)) / densities[dive_density_index(dive)]; + *((double *)value) = 0.01 * (array_uint16_le(abstract->data + SZ_CFG + 0x0018) - psurf) / density; break; - case DC_FIELD_SALINITY: - switch (dive_density_index(dive)) { - case 0: ((dc_salinity_t*)value)->type = DC_WATER_FRESH; ((dc_salinity_t*)value)->density = densities[dive_density_index(dive)]; break; - case 1: ((dc_salinity_t*)value)->type = DC_WATER_SALT; ((dc_salinity_t*)value)->density = densities[dive_density_index(dive)]; break; - case 2: ((dc_salinity_t*)value)->type = DC_WATER_SALT; ((dc_salinity_t*)value)->density = densities[dive_density_index(dive)]; break; - default: /* that's an error */ break; + salinity->density = density * 1000.0; + salinity->type = density_index == 0 ? DC_WATER_FRESH : DC_WATER_SALT; + break; + case DC_FIELD_ATMOSPHERIC: + *((double *)value) = 0.001 * array_uint16_le(abstract->data + 0x001E); + break; + case DC_FIELD_TEMPERATURE_MINIMUM: + *((double *)value) = (double)abstract->data[SZ_CFG + 0x0010]; + break; + case DC_FIELD_TEMPERATURE_MAXIMUM: + *((double *)value) = (double)abstract->data[SZ_CFG + 0x0011]; + break; + case DC_FIELD_DIVEMODE: + switch (abstract->data[0x002C]) { + case REC: + case TEC: + *((dc_divemode_t *)value) = DC_DIVEMODE_OC; + break; + case CCR: + *((dc_divemode_t *)value) = DC_DIVEMODE_CCR; + break; + case GAUGE: + *((dc_divemode_t *)value) = DC_DIVEMODE_GAUGE; + break; + default: + ERROR(abstract->context, "Corrupt dive mode in dive data"); + return DC_STATUS_DATAFORMAT; } break; - - case DC_FIELD_ATMOSPHERIC: - *((double*)value) = dive_Psurf(dive) / 1000.0; - break; - - // case DC_FIELD_TEMPERATURE_SURFACE: - - case DC_FIELD_TEMPERATURE_MINIMUM: - *((double*)value) = dive_temp_min(dive); - break; - - case DC_FIELD_TEMPERATURE_MAXIMUM: - *((double*)value) = dive_temp_max(dive); - break; - - case DC_FIELD_DIVEMODE: - *((dc_divemode_t*)value) = divemodes[dive_operatingmode(dive)]; - break; - - //case DC_FIELD_TANK: - //case DC_FIELD_TANK_COUNT: - case DC_FIELD_GASMIX_COUNT: - *((unsigned int*)value) = 8; + *((unsigned int *)value) = parser->ngasmixes; break; - case DC_FIELD_GASMIX: - gasmix->helium = 0.01 * dive_gas_pHe(dive, flags); - gasmix->oxygen = 0.01 * dive_gas_pO2(dive, 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->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium; break; - default: return DC_STATUS_UNSUPPORTED; } @@ -237,42 +229,88 @@ mclean_extreme_parser_get_field(dc_parser_t* abstract, dc_field_type_t type, uns } static dc_status_t -mclean_extreme_parser_samples_foreach(dc_parser_t* abstract, dc_sample_callback_t callback, void* userdata) +mclean_extreme_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata) { - const unsigned char* dive = abstract->data; - const unsigned int size = abstract->size; + mclean_extreme_parser_t *parser = (mclean_extreme_parser_t *)abstract; - const unsigned int interval = 20; // this should be dive[log end] - dive[log start]? - const int samples_cnt = dive_samples_cnt(dive); // number of samples to follow + if (abstract->size < SZ_HEADER) { + ERROR(abstract->context, "Corrupt dive data"); + return DC_STATUS_DATAFORMAT; + } - if (callback) { - unsigned int time = 0; + const unsigned int nsamples = array_uint16_le(abstract->data + 0x005C); - for (int i = 0; i < samples_cnt; ++i) { - dc_sample_value_t sample = { 0 }; + if (abstract->size != SZ_HEADER + nsamples * SZ_SAMPLE) { + ERROR(abstract->context, "Corrupt dive data"); + return DC_STATUS_DATAFORMAT; + } - sample.time = time; - callback(DC_SAMPLE_TIME, sample, userdata); + unsigned int ngasmixes = 0; + unsigned int gasmix[NGASMIXES] = {0}; + unsigned int gasmix_previous = INVALID; - sample.depth = sample_depth(dive, i) * 0.1; - callback(DC_SAMPLE_DEPTH, sample, userdata); + const unsigned int interval = 20; + unsigned int time = 0; + size_t offset = SZ_HEADER; + for (unsigned int i = 0; i < nsamples; ++i) { + dc_sample_value_t sample = { 0 }; - sample.temperature = sample_temperature(dive, i); - callback(DC_SAMPLE_TEMPERATURE, sample, userdata); + const unsigned int depth = array_uint16_le(abstract->data + offset + 0); + const unsigned int temperature = abstract->data[offset + 2]; + const unsigned int flags = abstract->data[offset + 3]; + const unsigned int ccr = flags & 0x80; + const unsigned int gasmix_id = (flags & 0x1C) >> 2; + const unsigned int sp_index = (flags & 0x60) >> 5; + const unsigned int setpoint = abstract->data[0x0013 + sp_index]; - sample.gasmix = sample_gas_index(dive, i); - callback(DC_SAMPLE_GASMIX, sample, userdata); + time += interval; + sample.time = time; + if (callback) callback(DC_SAMPLE_TIME, sample, userdata); - if (sample_ccr(dive, i)) { - const uint8_t sp_index = sample_sp_index(dive, i); + sample.depth = 0.1 * depth; + if (callback) callback(DC_SAMPLE_DEPTH, sample, userdata); - sample.setpoint = 100.0 * dive_setpoint(dive, sp_index); - if (callback) callback(DC_SAMPLE_SETPOINT, sample, userdata); + sample.temperature = temperature; + if (callback) callback(DC_SAMPLE_TEMPERATURE, sample, userdata); + + if (gasmix_id != gasmix_previous) { + // Find the gasmix in the list. + unsigned int idx = 0; + while (idx < ngasmixes) { + if (gasmix_id == gasmix[idx]) + break; + idx++; } - time += interval; + // Add it to list if not found. + if (idx >= ngasmixes) { + if (idx >= NGASMIXES) { + ERROR (abstract->context, "Maximum number of gas mixes reached."); + return DC_STATUS_DATAFORMAT; + } + gasmix[idx] = gasmix_id; + ngasmixes = idx + 1; + } + + sample.gasmix = idx; + if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata); + gasmix_previous = gasmix_id; } + + if (ccr) { + sample.setpoint = 0.01 * setpoint; + if (callback) callback(DC_SAMPLE_SETPOINT, sample, userdata); + } + + offset += SZ_SAMPLE; } + // Cache the data for later use. + for (unsigned int i = 0; i < ngasmixes; ++i) { + parser->gasmix[i] = gasmix[i]; + } + parser->ngasmixes = ngasmixes; + parser->cached = 1; + return DC_STATUS_SUCCESS; } diff --git a/src/parser.c b/src/parser.c index df80efc..dffb517 100644 --- a/src/parser.c +++ b/src/parser.c @@ -182,7 +182,7 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t fa rc = deepblu_parser_create (&parser, context); break; case DC_FAMILY_MCLEAN_EXTREME: - rc = mclean_extreme_parser_create(&parser, context); + rc = mclean_extreme_parser_create (&parser, context); break; default: return DC_STATUS_INVALIDARGS; diff --git a/src/tecdiving_divecomputereu.c b/src/tecdiving_divecomputereu.c index cf88b30..93190e2 100644 --- a/src/tecdiving_divecomputereu.c +++ b/src/tecdiving_divecomputereu.c @@ -376,6 +376,10 @@ tecdiving_divecomputereu_device_open (dc_device_t **out, dc_context_t *context, goto error_free; } + // Make sure everything is in a sane state. + dc_iostream_sleep (device->iostream, 100); + dc_iostream_purge (device->iostream, DC_DIRECTION_ALL); + // Send the init command. status = tecdiving_divecomputereu_send (device, CMD_INIT, NULL, 0); if (status != DC_STATUS_SUCCESS) {