From ae126d1009d79c0d0cdda865fd1080a47a2041b6 Mon Sep 17 00:00:00 2001 From: David Stipp Date: Wed, 2 Sep 2015 23:41:00 -0400 Subject: [PATCH] Add back Darwin/Mach/Apple portability Quite a few of the changes against the MalcolmRobb/dump1090 fork are incompatible with OSX. This patch adds back that cross platform support back. --- .travis.yml | 22 +++++-- Makefile | 20 ++++-- compat/clock_gettime/LICENSE | 28 +++++++++ compat/clock_gettime/README | 31 ++++++++++ compat/clock_gettime/clock_gettime.c | 79 ++++++++++++++++++++++++ compat/clock_gettime/clock_gettime.h | 26 ++++++++ compat/clock_nanosleep/LICENSE | 16 +++++ compat/clock_nanosleep/clock_nanosleep.c | 49 +++++++++++++++ compat/clock_nanosleep/clock_nanosleep.h | 27 ++++++++ compat/util.h | 20 ++++++ convert.c | 4 ++ dump1090.c | 7 +++ faup1090.c | 1 - net_io.c | 4 ++ 14 files changed, 324 insertions(+), 10 deletions(-) create mode 100644 compat/clock_gettime/LICENSE create mode 100644 compat/clock_gettime/README create mode 100644 compat/clock_gettime/clock_gettime.c create mode 100644 compat/clock_gettime/clock_gettime.h create mode 100644 compat/clock_nanosleep/LICENSE create mode 100644 compat/clock_nanosleep/clock_nanosleep.c create mode 100644 compat/clock_nanosleep/clock_nanosleep.h create mode 100644 compat/util.h diff --git a/.travis.yml b/.travis.yml index d6c686b..e99fbe7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,23 @@ language: c +os: + - linux + - osx + before_install: - - sudo add-apt-repository ppa:gqrx/releases -y - - sudo apt-get update -qq - - sudo apt-get install -y build-essential debhelper librtlsdr-dev libusb-1.0-0-dev pkg-config + - if [ `uname` = "Linux" ]; then + sudo add-apt-repository ppa:gqrx/releases -y; + sudo apt-get update -qq; + sudo apt-get install -y build-essential debhelper librtlsdr-dev libusb-1.0-0-dev pkg-config; + elif [ `uname` = "Darwin" ]; then + brew update; + brew install -v librtlsdr; + fi script: - - dpkg-buildpackage -b -us -uc + - if [ `uname` = "Linux" ]; then + dpkg-buildpackage -b -us -uc; + elif [ `uname` = "Darwin" ]; then + make; + make test; + fi \ No newline at end of file diff --git a/Makefile b/Makefile index 9314ec0..9560766 100644 --- a/Makefile +++ b/Makefile @@ -16,10 +16,20 @@ endif CPPFLAGS+=-DMODES_DUMP1090_VERSION=\"$(DUMP1090_VERSION)\" CFLAGS+=-O2 -g -Wall -Werror -W -LIBS=-lpthread -lm -lrt +LIBS=-lpthread -lm LIBS_RTL=`pkg-config --libs librtlsdr` CC=gcc +UNAME := $(shell uname) + +ifeq ($(UNAME), Linux) +LIBS+=-lrt +endif +ifeq ($(UNAME), Darwin) +# TODO: Putting GCC in C11 mode breaks things. +CFLAGS+=-std=c11 +endif + all: dump1090 view1090 %.o: %.c *.h @@ -27,17 +37,17 @@ all: dump1090 view1090 dump1090.o: CFLAGS += `pkg-config --cflags librtlsdr` -dump1090: dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o crc.o demod_2000.o demod_2400.o stats.o cpr.o icao_filter.o track.o util.o convert.o +dump1090: dump1090.o anet.o compat/clock_gettime/clock_gettime.o compat/clock_nanosleep/clock_nanosleep.o interactive.o mode_ac.o mode_s.o net_io.o crc.o demod_2000.o demod_2400.o stats.o cpr.o icao_filter.o track.o util.o convert.o $(CC) -g -o $@ $^ $(LIBS) $(LIBS_RTL) $(LDFLAGS) -view1090: view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o crc.o stats.o cpr.o icao_filter.o track.o util.o +view1090: view1090.o anet.o compat/clock_gettime/clock_gettime.o interactive.o mode_ac.o mode_s.o net_io.o crc.o stats.o cpr.o icao_filter.o track.o util.o $(CC) -g -o $@ $^ $(LIBS) $(LDFLAGS) -faup1090: faup1090.o anet.o mode_ac.o mode_s.o net_io.o crc.o stats.o cpr.o icao_filter.o track.o util.o +faup1090: faup1090.o anet.o compat/clock_gettime/clock_gettime.o mode_ac.o mode_s.o net_io.o crc.o stats.o cpr.o icao_filter.o track.o util.o $(CC) -g -o $@ $^ $(LIBS) $(LDFLAGS) clean: - rm -f *.o dump1090 view1090 faup1090 cprtests crctests + rm -f *.o compat/clock_gettime/*.o compat/clock_nanosleep/*.o dump1090 view1090 faup1090 cprtests crctests test: cprtests ./cprtests diff --git a/compat/clock_gettime/LICENSE b/compat/clock_gettime/LICENSE new file mode 100644 index 0000000..dceb70d --- /dev/null +++ b/compat/clock_gettime/LICENSE @@ -0,0 +1,28 @@ +/* + * Copyright (c), MM Weiss + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the MM Weiss nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ \ No newline at end of file diff --git a/compat/clock_gettime/README b/compat/clock_gettime/README new file mode 100644 index 0000000..e3ad8a6 --- /dev/null +++ b/compat/clock_gettime/README @@ -0,0 +1,31 @@ +/* + * clock_gettime_stub.c + * gcc -Wall -c clock_gettime_stub.c + * posix realtime functions; MacOS user space glue + */ + +/* @comment + * other possible implementation using intel builtin rdtsc + * rdtsc-workaround: http://www.mcs.anl.gov/~kazutomo/rdtsc.html + * + * we could get the ticks by doing this + * + * __asm __volatile("mov %%ebx, %%esi\n\t" + * "cpuid\n\t" + * "xchg %%esi, %%ebx\n\t" + * "rdtsc" + * : "=a" (a), + * "=d" (d) + * ); + + * we could even replace our tricky sched_yield call by assembly code to get a better accurency, + * anyway the following C stub will satisfy 99% of apps using posix clock_gettime call, + * moreover, the setter version (clock_settime) could be easly written using mach primitives: + * http://www.opensource.apple.com/source/xnu/xnu-${VERSION}/osfmk/man/ (clock_[set|get]_time) + * + * hackers don't be crackers, don't you use a flush toilet? + * + * + * @see draft: ./posix-realtime-stub/posix-realtime-stub.c + * + */ \ No newline at end of file diff --git a/compat/clock_gettime/clock_gettime.c b/compat/clock_gettime/clock_gettime.c new file mode 100644 index 0000000..2b28f43 --- /dev/null +++ b/compat/clock_gettime/clock_gettime.c @@ -0,0 +1,79 @@ +#ifdef __APPLE__ + +#include "clock_gettime.h" +#include // for clock_get_time +#include // for mach_timespec_t, CALENDAR_CLOCK, etc +#include // for KERN_SUCCESS, kern_return_t +#include // for host_get_clock_service +#include // for mach_host_self +#include // for clock_serv_t +#include // for sched_yield +#include // for EINVAL, errno +#include // for getpid + +int clock_gettime(clockid_t clk_id, struct timespec *tp) +{ + kern_return_t ret; + clock_serv_t clk; + clock_id_t clk_serv_id; + mach_timespec_t tm; + + uint64_t start, end, delta, nano; + + /* + task_basic_info_data_t tinfo; + task_thread_times_info_data_t ttinfo; + mach_msg_type_number_t tflag; + */ + + int retval = -1; + switch (clk_id) + { + case CLOCK_REALTIME: + case CLOCK_MONOTONIC: + clk_serv_id = clk_id == CLOCK_REALTIME ? CALENDAR_CLOCK : SYSTEM_CLOCK; + if (KERN_SUCCESS == (ret = host_get_clock_service(mach_host_self(), clk_serv_id, &clk))) + { + if (KERN_SUCCESS == (ret = clock_get_time(clk, &tm))) + { + tp->tv_sec = tm.tv_sec; + tp->tv_nsec = tm.tv_nsec; + retval = 0; + } + } + if (KERN_SUCCESS != ret) + { + errno = EINVAL; + retval = -1; + } + break; + case CLOCK_PROCESS_CPUTIME_ID: + case CLOCK_THREAD_CPUTIME_ID: + start = mach_absolute_time(); + if (clk_id == CLOCK_PROCESS_CPUTIME_ID) + { + getpid(); + } + else + { + sched_yield(); + } + end = mach_absolute_time(); + delta = end - start; + if (0 == __clock_gettime_inf.denom) + { + mach_timebase_info(&__clock_gettime_inf); + } + nano = delta * __clock_gettime_inf.numer / __clock_gettime_inf.denom; + tp->tv_sec = nano * 1e-9; + tp->tv_nsec = nano - (tp->tv_sec * 1e9); + retval = 0; + break; + default: + errno = EINVAL; + retval = -1; + } + return retval; +} + +#endif // __APPLE__ \ No newline at end of file diff --git a/compat/clock_gettime/clock_gettime.h b/compat/clock_gettime/clock_gettime.h new file mode 100644 index 0000000..2478104 --- /dev/null +++ b/compat/clock_gettime/clock_gettime.h @@ -0,0 +1,26 @@ +#ifdef __APPLE__ + +#ifndef CLOCK_GETTIME_H +#define CLOCK_GETTIME_H + +#include + +#ifndef CLOCKID_T +#define CLOCKID_T +typedef enum +{ + CLOCK_REALTIME, + CLOCK_MONOTONIC, + CLOCK_PROCESS_CPUTIME_ID, + CLOCK_THREAD_CPUTIME_ID +} clockid_t; +#endif // CLOCKID_T + +struct timespec; + +static mach_timebase_info_data_t __clock_gettime_inf; + +int clock_gettime(clockid_t clk_id, struct timespec *tp); + +#endif // CLOCK_GETTIME_H +#endif // __APPLE__ \ No newline at end of file diff --git a/compat/clock_nanosleep/LICENSE b/compat/clock_nanosleep/LICENSE new file mode 100644 index 0000000..120db7a --- /dev/null +++ b/compat/clock_nanosleep/LICENSE @@ -0,0 +1,16 @@ +/*********************************************************************** + * Copyright © 2006 Rémi Denis-Courmont. * + * This program is free software; you can redistribute and/or modify * + * it under the terms of the GNU General Public License as published * + * by the Free Software Foundation; version 2 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 General Public License * + * along with this program; if not, you can get it from: * + * http://www.gnu.org/copyleft/gpl.html * + ***********************************************************************/ \ No newline at end of file diff --git a/compat/clock_nanosleep/clock_nanosleep.c b/compat/clock_nanosleep/clock_nanosleep.c new file mode 100644 index 0000000..6dcecfb --- /dev/null +++ b/compat/clock_nanosleep/clock_nanosleep.c @@ -0,0 +1,49 @@ +/* + * clock_nanosleep.c - clock_nanosleep() replacement + */ + +#ifdef __APPLE__ + +#include "clock_nanosleep.h" +#include // for errno, EINVAL +#include // for nanosleep, NULL +#include "../clock_gettime/clock_gettime.h" // for clock_gettime + +int clock_nanosleep(clockid_t id, int flags, const struct timespec *ts, + struct timespec *ots) { + int ret; + + if (id != CLOCK_REALTIME) + return EINVAL; + + if (flags & TIMER_ABSTIME) { + struct timespec mine; + + if (clock_gettime(id, &mine)) + return errno; + + if (mine.tv_sec > ts->tv_sec) + return 0; // behind schedule + + if (mine.tv_nsec > ts->tv_nsec) { + if (mine.tv_sec == ts->tv_sec) + return 0; // behind schedule too + + mine.tv_nsec = 1000000000 + ts->tv_nsec - mine.tv_nsec; + mine.tv_sec++; + } + else + mine.tv_nsec = ts->tv_nsec - mine.tv_nsec; + + mine.tv_sec = ts->tv_sec - mine.tv_sec; + + /* With TIMER_ABSTIME, clock_nanosleep ignores */ + ret = nanosleep(&mine, NULL); + } + else + ret = nanosleep(ts, ots); + + return ret ? errno : 0; +} + +#endif // __APPLE__ \ No newline at end of file diff --git a/compat/clock_nanosleep/clock_nanosleep.h b/compat/clock_nanosleep/clock_nanosleep.h new file mode 100644 index 0000000..6e55db6 --- /dev/null +++ b/compat/clock_nanosleep/clock_nanosleep.h @@ -0,0 +1,27 @@ +#ifdef __APPLE__ + +#ifndef CLOCK_NANOSLEEP_H +#define CLOCK_NANOSLEEP_H + +#ifndef CLOCKID_T +#define CLOCKID_T +typedef enum +{ + CLOCK_REALTIME, + CLOCK_MONOTONIC, + CLOCK_PROCESS_CPUTIME_ID, + CLOCK_THREAD_CPUTIME_ID +} clockid_t; +#endif // CLOCKID_T + +#ifndef TIMER_ABSTIME +#define TIMER_ABSTIME 1 +#endif // TIMER_ABSTIME + +struct timespec; + +int clock_nanosleep (clockid_t id, int flags, const struct timespec *ts, + struct timespec *ots); + +#endif //CLOCK_NANOSLEEP_H +#endif // __APPLE__ \ No newline at end of file diff --git a/compat/util.h b/compat/util.h new file mode 100644 index 0000000..82bd99c --- /dev/null +++ b/compat/util.h @@ -0,0 +1,20 @@ +#ifndef COMPAT_UTIL_H +#define COMPAT_UTIL_H + +#include "clock_gettime/clock_gettime.h" +#include "clock_nanosleep/clock_nanosleep.h" + +/* + * Mach endian conversion + */ +#if defined(__APPLE__) +#include +#define bswap_16 OSSwapInt16 +#define bswap_32 OSSwapInt32 +#define bswap_64 OSSwapInt64 +#include +#define le16toh(x) OSSwapLittleToHostInt16(x) +#define le32toh(x) OSSwapLittleToHostInt32(x) +#endif + +#endif //COMPAT_UTIL_H diff --git a/convert.c b/convert.c index cb55dca..0d63355 100644 --- a/convert.c +++ b/convert.c @@ -19,6 +19,10 @@ #include "dump1090.h" +#ifdef __APPLE__ +#include "compat/util.h" +#endif + struct converter_state { float dc_a; float dc_b; diff --git a/dump1090.c b/dump1090.c index 6b9a4e3..51691b8 100644 --- a/dump1090.c +++ b/dump1090.c @@ -52,7 +52,14 @@ #include #include + +#ifdef __linux__ #include +#endif + +#ifdef __APPLE__ +#include "compat/util.h" +#endif static int verbose_device_search(char *s); diff --git a/faup1090.c b/faup1090.c index 8e21068..43e2959 100644 --- a/faup1090.c +++ b/faup1090.c @@ -50,7 +50,6 @@ #include "dump1090.h" #include -#include // // =============================== Initialization =========================== diff --git a/net_io.c b/net_io.c index 26601f4..eff6b19 100644 --- a/net_io.c +++ b/net_io.c @@ -54,6 +54,10 @@ #include +#ifdef __APPLE__ +#include "compat/util.h" +#endif + // // ============================= Networking ============================= //