diff --git a/configure.ac b/configure.ac index c1e126d..2d32a35 100644 --- a/configure.ac +++ b/configure.ac @@ -157,6 +157,7 @@ AC_CHECK_HEADERS([IOKit/serial/ioss.h]) AC_CHECK_HEADERS([getopt.h]) AC_CHECK_HEADERS([sys/param.h]) AC_CHECK_HEADERS([pthread.h]) +AC_CHECK_HEADERS([mach/mach_time.h]) # Checks for global variable declarations. AC_CHECK_DECLS([optreset]) @@ -169,6 +170,7 @@ AC_CHECK_MEMBERS([struct tm.tm_gmtoff],,,[ # Checks for library functions. AC_FUNC_STRERROR_R AC_CHECK_FUNCS([localtime_r gmtime_r timegm _mkgmtime]) +AC_CHECK_FUNCS([clock_gettime mach_absolute_time]) AC_CHECK_FUNCS([getopt_long]) # Checks for supported compiler options. diff --git a/msvc/libdivecomputer.vcproj b/msvc/libdivecomputer.vcproj index c54c3d7..1b1cd96 100644 --- a/msvc/libdivecomputer.vcproj +++ b/msvc/libdivecomputer.vcproj @@ -482,6 +482,10 @@ RelativePath="..\src\suunto_vyper_parser.c" > + + @@ -820,6 +824,10 @@ RelativePath="..\src\suunto_vyper2.h" > + + diff --git a/src/Makefile.am b/src/Makefile.am index e631c37..7ca5302 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,6 +24,7 @@ libdivecomputer_la_SOURCES = \ device-private.h device.c \ parser-private.h parser.c \ datetime.c \ + timer.h timer.c \ suunto_common.h suunto_common.c \ suunto_common2.h suunto_common2.c \ suunto_solution.h suunto_solution.c suunto_solution_parser.c \ diff --git a/src/timer.c b/src/timer.c new file mode 100644 index 0000000..36d1f8f --- /dev/null +++ b/src/timer.c @@ -0,0 +1,161 @@ +/* + * libdivecomputer + * + * Copyright (C) 2018 Jef Driesen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#ifdef _WIN32 +#define NOGDI +#include +#else +#include +#include +#ifdef HAVE_MACH_MACH_TIME_H +#include +#endif +#endif + +#include "timer.h" + +struct dc_timer_t { +#if defined (_WIN32) + LARGE_INTEGER timestamp; + LARGE_INTEGER frequency; +#elif defined (HAVE_CLOCK_GETTIME) + struct timespec timestamp; +#elif defined (HAVE_MACH_ABSOLUTE_TIME) + uint64_t timestamp; + mach_timebase_info_data_t info; +#else + struct timeval timestamp; +#endif +}; + +dc_status_t +dc_timer_new (dc_timer_t **out) +{ + dc_timer_t *timer = NULL; + + if (out == NULL) + return DC_STATUS_INVALIDARGS; + + timer = (dc_timer_t *) malloc (sizeof (dc_timer_t)); + if (timer == NULL) { + return DC_STATUS_NOMEMORY; + } + +#if defined (_WIN32) + if (!QueryPerformanceFrequency(&timer->frequency) || + !QueryPerformanceCounter(&timer->timestamp)) { + free(timer); + return DC_STATUS_IO; + } +#elif defined (HAVE_CLOCK_GETTIME) + if (clock_gettime(CLOCK_MONOTONIC, &timer->timestamp) != 0) { + free(timer); + return DC_STATUS_IO; + } +#elif defined (HAVE_MACH_ABSOLUTE_TIME) + if (mach_timebase_info(&timer->info) != KERN_SUCCESS) { + free(timer); + return DC_STATUS_IO; + } + + timer->timestamp = mach_absolute_time(); +#else + if (gettimeofday (&timer->timestamp, NULL) != 0) { + free(timer); + return DC_STATUS_IO; + } +#endif + + *out = timer; + + return DC_STATUS_SUCCESS; +} + +dc_status_t +dc_timer_now (dc_timer_t *timer, dc_usecs_t *usecs) +{ + dc_status_t status = DC_STATUS_SUCCESS; + dc_usecs_t value = 0; + + if (timer == NULL) { + status = DC_STATUS_INVALIDARGS; + goto out; + } + +#if defined (_WIN32) + LARGE_INTEGER now; + if (!QueryPerformanceCounter(&now)) { + status = DC_STATUS_IO; + goto out; + } + + value = (now.QuadPart - timer->timestamp.QuadPart) * 1000000 / timer->frequency.QuadPart; +#elif defined (HAVE_CLOCK_GETTIME) + struct timespec now, delta; + if (clock_gettime(CLOCK_MONOTONIC, &now) != 0) { + status = DC_STATUS_IO; + goto out; + } + + if (now.tv_nsec < timer->timestamp.tv_nsec) { + delta.tv_nsec = 1000000000 + now.tv_nsec - timer->timestamp.tv_nsec; + delta.tv_sec = now.tv_sec - timer->timestamp.tv_sec - 1; + } else { + delta.tv_nsec = now.tv_nsec - timer->timestamp.tv_nsec; + delta.tv_sec = now.tv_sec - timer->timestamp.tv_sec; + } + + value = (dc_usecs_t) delta.tv_sec * 1000000 + delta.tv_nsec / 1000; +#elif defined (HAVE_MACH_ABSOLUTE_TIME) + uint64_t now = mach_absolute_time(); + value = (now - timer->timestamp) * timer->info.numer / timer->info.denom; +#else + struct timeval now, delta; + if (gettimeofday (&now, NULL) != 0) { + status = DC_STATUS_IO; + goto out; + } + + timersub (&now, &timer->timestamp, &delta); + + value = (dc_usecs_t) delta.tv_sec * 1000000 + delta.tv_usec; +#endif + +out: + if (usecs) + *usecs = value; + + return status; +} + +dc_status_t +dc_timer_free (dc_timer_t *timer) +{ + free (timer); + + return DC_STATUS_SUCCESS; +} diff --git a/src/timer.h b/src/timer.h new file mode 100644 index 0000000..651991f --- /dev/null +++ b/src/timer.h @@ -0,0 +1,51 @@ +/* + * libdivecomputer + * + * Copyright (C) 2018 Jef Driesen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifndef DC_TIMER_H +#define DC_TIMER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if defined (_WIN32) && !defined (__GNUC__) +typedef unsigned __int64 dc_usecs_t; +#else +typedef unsigned long long dc_usecs_t; +#endif + +typedef struct dc_timer_t dc_timer_t; + +dc_status_t +dc_timer_new (dc_timer_t **timer); + +dc_status_t +dc_timer_now (dc_timer_t *timer, dc_usecs_t *usecs); + +dc_status_t +dc_timer_free (dc_timer_t *timer); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* DC_TIMER_H */