lib_LTLIBRARIES = libserialport.la
-libserialport_la_SOURCES = serialport.c libserialport_internal.h
+libserialport_la_SOURCES = serialport.c timing.c libserialport_internal.h
if LINUX
libserialport_la_SOURCES += linux.c linux_termios.c linux_termios.h
endif
SP_PRIV enum sp_return get_port_details(struct sp_port *port);
SP_PRIV enum sp_return list_ports(struct sp_port ***list);
+/* Timing abstraction */
+
+struct time {
+#ifdef _WIN32
+ int64_t ticks;
+#else
+ struct timeval tv;
+#endif
+};
+
+struct timeout {
+ unsigned int ms, limit_ms;
+ struct time start, now, end, delta, delta_max;
+ struct timeval delta_tv;
+ bool calls_started, overflow;
+};
+
+SP_PRIV void time_get(struct time *time);
+SP_PRIV void time_set_ms(struct time *time, unsigned int ms);
+SP_PRIV void time_add(const struct time *a, const struct time *b, struct time *result);
+SP_PRIV void time_sub(const struct time *a, const struct time *b, struct time *result);
+SP_PRIV bool time_greater(const struct time *a, const struct time *b);
+SP_PRIV void time_as_timeval(const struct time *time, struct timeval *tv);
+SP_PRIV unsigned int time_as_ms(const struct time *time);
+SP_PRIV void timeout_start(struct timeout *timeout, unsigned int timeout_ms);
+SP_PRIV void timeout_limit(struct timeout *timeout, unsigned int limit_ms);
+SP_PRIV bool timeout_check(struct timeout *timeout);
+SP_PRIV void timeout_update(struct timeout *timeout);
+SP_PRIV struct timeval *timeout_timeval(struct timeout *timeout);
+SP_PRIV unsigned int timeout_remaining_ms(struct timeout *timeout);
+
#endif
static enum sp_return set_config(struct sp_port *port, struct port_data *data,
const struct sp_port_config *config);
-/* Timing abstraction */
-
-struct time {
-#ifdef _WIN32
- int64_t ticks;
-#else
- struct timeval tv;
-#endif
-};
-
-struct timeout {
- unsigned int ms, limit_ms;
- struct time start, now, end, delta, delta_max;
- struct timeval delta_tv;
- bool calls_started, overflow;
-};
-
-static void time_get(struct time *time)
-{
-#ifdef _WIN32
- LARGE_INTEGER count;
- QueryPerformanceCounter(&count);
- time->ticks = count.QuadPart;
-#elif defined(HAVE_CLOCK_GETTIME)
- struct timespec ts;
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
- clock_gettime(CLOCK_REALTIME, &ts);
- time->tv.tv_sec = ts.tv_sec;
- time->tv.tv_usec = ts.tv_nsec / 1000;
-#elif defined(__APPLE__)
- mach_timebase_info_data_t info;
- mach_timebase_info(&info);
- uint64_t ticks = mach_absolute_time();
- uint64_t ns = (ticks * info.numer) / info.denom;
- time->tv.tv_sec = ns / 1000000000;
- time->tv.tv_usec = (ns % 1000000000) / 1000;
-#else
- gettimeofday(&time->tv, NULL);
-#endif
-}
-
-static void time_set_ms(struct time *time, unsigned int ms)
-{
-#ifdef _WIN32
- LARGE_INTEGER frequency;
- QueryPerformanceFrequency(&frequency);
- time->ticks = ms * (frequency.QuadPart / 1000);
-#else
- time->tv.tv_sec = ms / 1000;
- time->tv.tv_usec = (ms % 1000) * 1000;
-#endif
-}
-
-static void time_add(const struct time *a,
- const struct time *b, struct time *result)
-{
-#ifdef _WIN32
- result->ticks = a->ticks + b->ticks;
-#else
- timeradd(&a->tv, &b->tv, &result->tv);
-#endif
-}
-
-static void time_sub(const struct time *a,
- const struct time *b, struct time *result)
-{
-#ifdef _WIN32
- result->ticks = a->ticks - b->ticks;
-#else
- timersub(&a->tv, &b->tv, &result->tv);
-#endif
-}
-
-static bool time_greater(const struct time *a, const struct time *b)
-{
-#ifdef _WIN32
- return (a->ticks > b->ticks);
-#else
- return timercmp(&a->tv, &b->tv, >);
-#endif
-}
-
-static void time_as_timeval(const struct time *time, struct timeval *tv)
-{
-#ifdef _WIN32
- LARGE_INTEGER frequency;
- QueryPerformanceFrequency(&frequency);
- tv->tv_sec = time->ticks / frequency.QuadPart;
- tv->tv_usec = (time->ticks % frequency.QuadPart) /
- (frequency.QuadPart / 1000000);
-#else
- *tv = time->tv;
-#endif
-}
-
-static unsigned int time_as_ms(const struct time *time)
-{
-#ifdef _WIN32
- LARGE_INTEGER frequency;
- QueryPerformanceFrequency(&frequency);
- return time->ticks / (frequency.QuadPart / 1000);
-#else
- return time->tv.tv_sec * 1000 + time->tv.tv_usec / 1000;
-#endif
-}
-
-static void timeout_start(struct timeout *timeout, unsigned int timeout_ms)
-{
- timeout->ms = timeout_ms;
-
- /* Get time at start of operation. */
- time_get(&timeout->start);
- /* Define duration of timeout. */
- time_set_ms(&timeout->delta, timeout_ms);
- /* Calculate time at which we should give up. */
- time_add(&timeout->start, &timeout->delta, &timeout->end);
- /* Disable limit unless timeout_limit() called. */
- timeout->limit_ms = 0;
- /* First blocking call has not yet been made. */
- timeout->calls_started = false;
-}
-
-static void timeout_limit(struct timeout *timeout, unsigned int limit_ms)
-{
- timeout->limit_ms = limit_ms;
- timeout->overflow = (timeout->ms > timeout->limit_ms);
- time_set_ms(&timeout->delta_max, timeout->limit_ms);
-}
-
-static bool timeout_check(struct timeout *timeout)
-{
- if (!timeout->calls_started)
- return false;
-
- if (timeout->ms == 0)
- return false;
-
- time_get(&timeout->now);
- time_sub(&timeout->end, &timeout->now, &timeout->delta);
- if (timeout->limit_ms)
- if ((timeout->overflow = time_greater(&timeout->delta, &timeout->delta_max)))
- timeout->delta = timeout->delta_max;
-
- return time_greater(&timeout->now, &timeout->end);
-}
-
-static void timeout_update(struct timeout *timeout)
-{
- timeout->calls_started = true;
-}
-
-#ifndef _WIN32
-static struct timeval *timeout_timeval(struct timeout *timeout)
-{
- if (timeout->ms == 0)
- return NULL;
-
- time_as_timeval(&timeout->delta, &timeout->delta_tv);
-
- return &timeout->delta_tv;
-}
-#endif
-
-static unsigned int timeout_remaining_ms(struct timeout *timeout)
-{
- if (timeout->limit_ms && timeout->overflow)
- return timeout->limit_ms;
- else
- return time_as_ms(&timeout->delta);
-}
-
SP_API enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
{
struct sp_port *port;
--- /dev/null
+/*
+ * This file is part of the libserialport project.
+ *
+ * Copyright (C) 2019 Martin Ling <martin-libserialport@earth.li>
+ *
+ * This program 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 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include "libserialport.h"
+#include "libserialport_internal.h"
+
+SP_PRIV void time_get(struct time *time)
+{
+#ifdef _WIN32
+ LARGE_INTEGER count;
+ QueryPerformanceCounter(&count);
+ time->ticks = count.QuadPart;
+#elif defined(HAVE_CLOCK_GETTIME)
+ struct timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
+ clock_gettime(CLOCK_REALTIME, &ts);
+ time->tv.tv_sec = ts.tv_sec;
+ time->tv.tv_usec = ts.tv_nsec / 1000;
+#elif defined(__APPLE__)
+ mach_timebase_info_data_t info;
+ mach_timebase_info(&info);
+ uint64_t ticks = mach_absolute_time();
+ uint64_t ns = (ticks * info.numer) / info.denom;
+ time->tv.tv_sec = ns / 1000000000;
+ time->tv.tv_usec = (ns % 1000000000) / 1000;
+#else
+ gettimeofday(&time->tv, NULL);
+#endif
+}
+
+SP_PRIV void time_set_ms(struct time *time, unsigned int ms)
+{
+#ifdef _WIN32
+ LARGE_INTEGER frequency;
+ QueryPerformanceFrequency(&frequency);
+ time->ticks = ms * (frequency.QuadPart / 1000);
+#else
+ time->tv.tv_sec = ms / 1000;
+ time->tv.tv_usec = (ms % 1000) * 1000;
+#endif
+}
+
+SP_PRIV void time_add(const struct time *a,
+ const struct time *b, struct time *result)
+{
+#ifdef _WIN32
+ result->ticks = a->ticks + b->ticks;
+#else
+ timeradd(&a->tv, &b->tv, &result->tv);
+#endif
+}
+
+SP_PRIV void time_sub(const struct time *a,
+ const struct time *b, struct time *result)
+{
+#ifdef _WIN32
+ result->ticks = a->ticks - b->ticks;
+#else
+ timersub(&a->tv, &b->tv, &result->tv);
+#endif
+}
+
+SP_PRIV bool time_greater(const struct time *a, const struct time *b)
+{
+#ifdef _WIN32
+ return (a->ticks > b->ticks);
+#else
+ return timercmp(&a->tv, &b->tv, >);
+#endif
+}
+
+SP_PRIV void time_as_timeval(const struct time *time, struct timeval *tv)
+{
+#ifdef _WIN32
+ LARGE_INTEGER frequency;
+ QueryPerformanceFrequency(&frequency);
+ tv->tv_sec = time->ticks / frequency.QuadPart;
+ tv->tv_usec = (time->ticks % frequency.QuadPart) /
+ (frequency.QuadPart / 1000000);
+#else
+ *tv = time->tv;
+#endif
+}
+
+SP_PRIV unsigned int time_as_ms(const struct time *time)
+{
+#ifdef _WIN32
+ LARGE_INTEGER frequency;
+ QueryPerformanceFrequency(&frequency);
+ return time->ticks / (frequency.QuadPart / 1000);
+#else
+ return time->tv.tv_sec * 1000 + time->tv.tv_usec / 1000;
+#endif
+}
+
+SP_PRIV void timeout_start(struct timeout *timeout, unsigned int timeout_ms)
+{
+ timeout->ms = timeout_ms;
+
+ /* Get time at start of operation. */
+ time_get(&timeout->start);
+ /* Define duration of timeout. */
+ time_set_ms(&timeout->delta, timeout_ms);
+ /* Calculate time at which we should give up. */
+ time_add(&timeout->start, &timeout->delta, &timeout->end);
+ /* Disable limit unless timeout_limit() called. */
+ timeout->limit_ms = 0;
+ /* First blocking call has not yet been made. */
+ timeout->calls_started = false;
+}
+
+SP_PRIV void timeout_limit(struct timeout *timeout, unsigned int limit_ms)
+{
+ timeout->limit_ms = limit_ms;
+ timeout->overflow = (timeout->ms > timeout->limit_ms);
+ time_set_ms(&timeout->delta_max, timeout->limit_ms);
+}
+
+SP_PRIV bool timeout_check(struct timeout *timeout)
+{
+ if (!timeout->calls_started)
+ return false;
+
+ if (timeout->ms == 0)
+ return false;
+
+ time_get(&timeout->now);
+ time_sub(&timeout->end, &timeout->now, &timeout->delta);
+ if (timeout->limit_ms)
+ if ((timeout->overflow = time_greater(&timeout->delta, &timeout->delta_max)))
+ timeout->delta = timeout->delta_max;
+
+ return time_greater(&timeout->now, &timeout->end);
+}
+
+SP_PRIV void timeout_update(struct timeout *timeout)
+{
+ timeout->calls_started = true;
+}
+
+#ifndef _WIN32
+SP_PRIV struct timeval *timeout_timeval(struct timeout *timeout)
+{
+ if (timeout->ms == 0)
+ return NULL;
+
+ time_as_timeval(&timeout->delta, &timeout->delta_tv);
+
+ return &timeout->delta_tv;
+}
+#endif
+
+SP_PRIV unsigned int timeout_remaining_ms(struct timeout *timeout)
+{
+ if (timeout->limit_ms && timeout->overflow)
+ return timeout->limit_ms;
+ else
+ return time_as_ms(&timeout->delta);
+}