include_directories(/usr/include/libusb-1.0)
list(APPEND LIBSRC hidapi/linux/hid-libusb.c)
endif()
-list(APPEND LIBSRC src/touchmouse.c)
+list(APPEND LIBSRC src/touchmouse.c src/mono_timer.c)
set(CMAKE_C_FLAGS "-Wall -ggdb")
--- /dev/null
+/* This file is intended to make it easier to work with monotonic timers on
+ * multiple platforms, since there's no single API for doing so.
+ *
+ * On Windows, we use QueryPerformanceCounter and QueryPerformanceFrequency
+ * On OSX, we use mach_absolute_time()
+ * On Linux, we use clock_gettime() with CLOCK_MONOTONIC
+ *
+ * Since I find this problem worth solving somewhat permanently:
+ *
+ * I hereby release this file into the public domain.
+ */
+
+#include "mono_timer.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#ifdef __APPLE__
+#include <mach/mach_time.h>
+#endif
+
+#ifdef __linux__
+#include <time.h>
+#endif
+
+#ifdef _WIN32
+uint64_t mono_timer_nanos() {
+ LARGE_INTEGER freq;
+ LARGE_INTEGER count;
+ if (!QueryPerformanceFrequency(&freq)) return 0;
+ if (!QueryPerformanceCounter(&count)) return 0;
+ // count / freq = seconds, so count / freq * 1e9 = nanoseconds
+ return (uint64_t)(count.QuadPart * 1000000000 / freq.QuadPart);
+}
+#endif // _WIN32
+#ifdef __APPLE__
+uint64_t mono_timer_nanos() {
+ mach_timebase_info_data_t info;
+ mach_timebase_info(&info);
+ return mach_absolute_time() * info.numer / info.denom;
+}
+#endif // APPLE
+#ifdef __linux__
+uint64_t mono_timer_nanos() {
+ struct timespec ts;
+ if(clock_gettime(CLOCK_MONOTONIC, &ts) != 0) return 0;
+ uint64_t nanos = (uint64_t)ts.tv_sec * 1000000000;
+ nanos += ts.tv_nsec;
+ return nanos;
+}
+#endif // __linux__
--- /dev/null
+/* This file is intended to make it easier to work with monotonic timers on
+ * multiple platforms, since there's no single API for doing so.
+ *
+ * On Windows, we use QueryPerformanceCounter and QueryPerformanceFrequency
+ * On OSX, we use mach_absolute_time()
+ * On Linux, we use clock_gettime() with CLOCK_MONOTONIC
+ * Other platforms are currently unsupported.
+ *
+ * Since I find this problem worth solving somewhat permanently:
+ *
+ * I hereby release this file into the public domain.
+ */
+#ifndef __MONO_TIMER_H__
+#define __MONO_TIMER_H__
+
+#include <stdint.h>
+
+// Returns the current time in nanoseconds since an arbitrary epoch. This
+// value is supposed to be stable and increase monotonically when called from
+// the same process, up to the maximum guarantee that can be provided by the
+// underlying OS.
+// Returns 0 on error.
+uint64_t mono_timer_nanos();
+
+#endif // __MONO_TIMER_H__
#include <stdint.h>
#include "touchmouse-internal.h"
+#include "mono_timer.h"
#pragma pack(1)
// The USB HID reports that contain our data are always 32 bytes, with the
int touchmouse_process_events_timeout(touchmouse_device *dev, int milliseconds) {
unsigned char data[256] = {};
int res;
- int millisleft = milliseconds;
uint8_t first_timestamp_read = 0;
uint8_t last_timestamp = 0;
- while(millisleft) { // TODO: make this TIME_NOT_YET_EXPIRED
- res = hid_read_timeout(dev->dev, data, 255, millisleft); // TODO: fix this to be
- // the right number of milliseconds
+ uint64_t deadline;
+ if(milliseconds == -1) {
+ deadline = (uint64_t)(-1);
+ } else {
+ deadline = mono_timer_nanos() + (milliseconds * 1000000);
+ }
+ uint64_t nanos = mono_timer_nanos();
+ if (nanos == 0 || deadline == 0) {
+ fprintf(stderr, "timer function returned an error, erroring out since we have no timer\n");
+ return -1;
+ }
+ do {
+ res = hid_read_timeout(dev->dev, data, 255, (deadline - nanos) / 1000000 );
if (res < 0 ) {
fprintf(stderr, "hid_read() failed: %d\n", res);
return -1;
}
}
}
- }
+ nanos = mono_timer_nanos();
+ } while(nanos < deadline);
return 0;
}