From 848723807d24f29c76be132c7898d1ef439aa99a Mon Sep 17 00:00:00 2001 From: Arian Date: Sun, 2 Aug 2020 16:18:49 +0200 Subject: [PATCH] davinci: gps: Import gnsspps from LA.UM.8.9.r1-03800-sm6150.0 Change-Id: Ib047a59a195cb6ead9438d74403cad7031804e6e --- gps/gnsspps/Android.mk | 36 ++++ gps/gnsspps/Makefile.am | 37 ++++ gps/gnsspps/configure.ac | 70 +++++++ gps/gnsspps/gnsspps.c | 391 ++++++++++++++++++++++++++++++++++++++ gps/gnsspps/gnsspps.h | 45 +++++ gps/gnsspps/gnsspps.pc.in | 10 + gps/gnsspps/timepps.h | 106 +++++++++++ 7 files changed, 695 insertions(+) create mode 100644 gps/gnsspps/Android.mk create mode 100644 gps/gnsspps/Makefile.am create mode 100644 gps/gnsspps/configure.ac create mode 100644 gps/gnsspps/gnsspps.c create mode 100644 gps/gnsspps/gnsspps.h create mode 100644 gps/gnsspps/gnsspps.pc.in create mode 100644 gps/gnsspps/timepps.h diff --git a/gps/gnsspps/Android.mk b/gps/gnsspps/Android.mk new file mode 100644 index 0000000..f87b674 --- /dev/null +++ b/gps/gnsspps/Android.mk @@ -0,0 +1,36 @@ +ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),) +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libgnsspps +LOCAL_MODULE_PATH_32 := $(TARGET_OUT_VENDOR)/lib +LOCAL_MODULE_PATH_64 := $(TARGET_OUT_VENDOR)/lib64 +LOCAL_MODULE_TAGS := optional + +LOCAL_SHARED_LIBRARIES := \ + libutils \ + libcutils \ + libgps.utils \ + liblog + +LOCAL_SRC_FILES += \ + gnsspps.c + +LOCAL_CFLAGS += \ + -fno-short-enums \ + -D_ANDROID_ + +## Includes +LOCAL_HEADER_LIBRARIES := \ + libgps.utils_headers \ + libloc_pla_headers +LOCAL_CFLAGS += $(GNSS_CFLAGS) +include $(BUILD_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := libgnsspps_headers +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) +include $(BUILD_HEADER_LIBRARY) + +endif diff --git a/gps/gnsspps/Makefile.am b/gps/gnsspps/Makefile.am new file mode 100644 index 0000000..c990be0 --- /dev/null +++ b/gps/gnsspps/Makefile.am @@ -0,0 +1,37 @@ +AM_CFLAGS = \ + $(LOCPLA_CFLAGS) \ + $(GPSUTILS_CFLAGS) \ + -I$(WORKSPACE)/system/core/include \ + -I./ + +ACLOCAL_AMFLAGS = -I m4 + +libgnsspps_la_SOURCES = \ + gnsspps.c + +if USE_GLIB +libgnsspps_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@ +libgnsspps_la_LDFLAGS = -lstdc++ -Wl,-z,defs -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0 +libgnsspps_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@ +else +libgnsspps_la_CFLAGS = $(AM_CFLAGS) +libgnsspps_la_LDFLAGS = -Wl,-z,defs -lpthread -shared -version-info 1:0:0 +libgnsspps_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) +endif + +libgnsspps_la_LIBADD = -lstdc++ $(GPSUTILS_LIBS) + +library_include_HEADERS = \ + gnsspps.h + +#Create and Install libraries +lib_LTLIBRARIES = libgnsspps.la + +library_includedir = $(pkgincludedir) +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = gnsspps.pc +EXTRA_DIST = $(pkgconfig_DATA) + + + + diff --git a/gps/gnsspps/configure.ac b/gps/gnsspps/configure.ac new file mode 100644 index 0000000..eb87bc1 --- /dev/null +++ b/gps/gnsspps/configure.ac @@ -0,0 +1,70 @@ +# configure.ac -- Autoconf script for gps lbs-core +# +# Process this file with autoconf to produce a configure script + +# Requires autoconf tool later than 2.61 +AC_PREREQ(2.61) +# Initialize the gps lbs-core package version 1.0.0 +AC_INIT([gnsspps],1.0.0) +# Does not strictly follow GNU Coding standards +AM_INIT_AUTOMAKE([foreign]) +# Disables auto rebuilding of configure, Makefile.ins +AM_MAINTAINER_MODE +# Verifies the --srcdir is correct by checking for the path +AC_CONFIG_SRCDIR([Makefile.am]) +# defines some macros variable to be included by source +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) + +# Checks for programs. +AC_PROG_LIBTOOL +AC_PROG_CXX +AC_PROG_CC +AM_PROG_CC_C_O +AC_PROG_AWK +AC_PROG_CPP +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +PKG_PROG_PKG_CONFIG + +# Checks for libraries. +PKG_CHECK_MODULES([GPSUTILS], [gps-utils]) +AC_SUBST([GPSUTILS_CFLAGS]) +AC_SUBST([GPSUTILS_LIBS]) + +AC_ARG_WITH([locpla_includes], + AC_HELP_STRING([--with-locpla-includes=@<:@dir@:>@], + [Specify the path to locpla-includes in loc-pla_git.bb]), + [locpla_incdir=$withval], + with_locpla_includes=no) + +if test "x${with_locpla_includes}" != "xno"; then + AC_SUBST(LOCPLA_CFLAGS, "-I${locpla_incdir}") +fi + +AC_ARG_WITH([glib], + AC_HELP_STRING([--with-glib], + [enable glib, building HLOS systems which use glib])) + +if (test "x${with_glib}" = "xyes"); then + AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib]) + PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes, + AC_MSG_ERROR(GThread >= 2.16 is required)) + PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes, + AC_MSG_ERROR(GLib >= 2.16 is required)) + GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS" + GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS" + + AC_SUBST(GLIB_CFLAGS) + AC_SUBST(GLIB_LIBS) +fi + +AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes") + +AC_CONFIG_FILES([ \ + Makefile \ + gnsspps.pc + ]) + +AC_OUTPUT diff --git a/gps/gnsspps/gnsspps.c b/gps/gnsspps/gnsspps.c new file mode 100644 index 0000000..b27fd77 --- /dev/null +++ b/gps/gnsspps/gnsspps.c @@ -0,0 +1,391 @@ +/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of The Linux Foundatoin, 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 "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "loc_cfg.h" +#include +#include +#include + +#define BILLION_NSEC (1E9) + +typedef struct timespec pps_sync_time; + +//DRsync kernel timestamp +static struct timespec drsyncKernelTs = {0,0}; +//DRsync userspace timestamp +static struct timespec drsyncUserTs = {0,0}; + +static struct timespec prevDrsyncKernelTs = {0,0}; + +//flag to stop fetching timestamp +static int isActive = 0; +static pps_handle handle; + +static pthread_mutex_t ts_lock; +static int skipPPSPulseCnt = 0; +static int gnssOutageInSec = 1; +static loc_param_s_type gps_conf_param_table[] = +{ + {"IGNORE_PPS_PULSE_COUNT", &skipPPSPulseCnt, NULL, 'n'}, + {"GNSS_OUTAGE_DURATION", &gnssOutageInSec, NULL, 'n'} +}; + +typedef enum { + KERNEL_REPORTED_CLOCK_BOOTTIME = 0, + KERNEL_REPORTED_CLOCK_REALTIME, + KERNEL_REPORTED_CLOCK_UNKNOWN = 0xfe, + KERNEL_REPORTED_CLOCK_MAX = 0xff +} kernel_reported_time_e; + + /* checks the PPS source and opens it */ +int check_device(char *path, pps_handle *handle) +{ + int ret; + + /* Try to find the source by using the supplied "path" name */ + ret = open(path, O_RDONLY); + if (ret < 0) + { + LOC_LOGV("%s:%d unable to open device %s", __func__, __LINE__, path); + return ret; + } + + /* Open the PPS source */ + ret = pps_create(ret, handle); + if (ret < 0) + { + LOC_LOGV( "%s:%d cannot create a PPS source from device %s", __func__, __LINE__, path); + return -1; + } + return 0; +} + + +/* calculate the time difference between two given times in argument - +** returns the result in timeDifference parametter*/ +static inline void calculate_time_difference(pps_sync_time time1, + pps_sync_time time2, pps_sync_time* timeDifference) +{ + if (time2.tv_nsec < time1.tv_nsec) { + timeDifference->tv_sec = time2.tv_sec - 1 - time1.tv_sec; + timeDifference->tv_nsec = BILLION_NSEC + time2.tv_nsec - time1.tv_nsec; + } else { + timeDifference->tv_sec = time2.tv_sec - time1.tv_sec; + timeDifference->tv_nsec = time2.tv_nsec - time1.tv_nsec; + } +} + +/*add two timespec values and return the result in third resultTime parameter*/ +static inline void pps_sync_time_add(pps_sync_time time1, + pps_sync_time time2, pps_sync_time* resultTime) +{ + if (time2.tv_nsec + time1.tv_nsec >= BILLION_NSEC) { + resultTime->tv_sec = time2.tv_sec + time1.tv_sec + 1; + resultTime->tv_nsec = time2.tv_nsec + time1.tv_nsec - BILLION_NSEC; + } else { + resultTime->tv_sec = time2.tv_sec + time1.tv_sec; + resultTime->tv_nsec = time2.tv_nsec + time1.tv_nsec; + } +} + +#define MAX_REALTIME_OFFSET_DELTA_DIFFERENCE 10 +#define MAX_PPS_KERNEL_TO_USERSPACE_LATENCY 100 /*in milli-second*/ + +static inline double convertTimeToMilliSec(pps_sync_time timeToConvert) +{ + return ((double)(timeToConvert.tv_sec * 1000) + (double)(timeToConvert.tv_nsec * 0.000001)); +} + +/*returnValue: 1 = offsetTime OK, 0 = offsetTime NOT OK*/ +static inline bool isTimeOffsetOk(pps_sync_time offsetTime) +{ + double offsetInMillis = convertTimeToMilliSec(offsetTime); + return (fabs(offsetInMillis) <= MAX_REALTIME_OFFSET_DELTA_DIFFERENCE)? true: false; +} + +/*check whether kernel PPS timestamp is a CLOCK_BOOTTIME or CLOCK_REALTIME*/ +static kernel_reported_time_e get_reported_time_type(pps_sync_time userBootTs, + pps_sync_time userRealTs, + pps_sync_time kernelTs) +{ + double userRealMs, userBootMs, kernelTsMs; + kernel_reported_time_e reportedTime = KERNEL_REPORTED_CLOCK_UNKNOWN; + + userRealMs = convertTimeToMilliSec(userRealTs); + userBootMs = convertTimeToMilliSec(userBootTs); + kernelTsMs = convertTimeToMilliSec(kernelTs); + + if(fabs(userBootMs - kernelTsMs) <= MAX_PPS_KERNEL_TO_USERSPACE_LATENCY) { + reportedTime = KERNEL_REPORTED_CLOCK_BOOTTIME; + } else if (fabs(userRealMs - kernelTsMs) <= MAX_PPS_KERNEL_TO_USERSPACE_LATENCY) { + reportedTime = KERNEL_REPORTED_CLOCK_REALTIME; + } else { + reportedTime = KERNEL_REPORTED_CLOCK_UNKNOWN; + } + + LOC_LOGV("[%s] Detected PPS timestamp type (0:Boot, 1:Real, 0xfe:Unknown):0x%x", + __func__, reportedTime); + + return reportedTime; +} + +/*compute_real_to_boot_time - converts the kernel real time stamp to boot time reference*/ +static int compute_real_to_boot_time(pps_info ppsFetchTime) +{ + int retVal = 0; + /*Offset between REAL_TIME to BOOT_TIME*/ + static pps_sync_time time_offset = {0, 0}; + pps_sync_time drSyncUserRealTs, drSyncUserBootTs; + pps_sync_time deltaRealToBootTime = {0, 0}; + pps_sync_time deltaOffsetTime = {0, 0}; + kernel_reported_time_e ppsTimeType; + + retVal = clock_gettime(CLOCK_BOOTTIME,&drSyncUserBootTs); + if (retVal != 0) { + LOC_LOGE("[%s]Error Reading CLOCK_BOOTTIME", __func__); + retVal = -1; + goto exit0; + } + retVal = clock_gettime(CLOCK_REALTIME,&drSyncUserRealTs); + if (retVal != 0){ + LOC_LOGE("[%s]Error Reading CLOCK_REALTIME", __func__); + retVal = -1; + goto exit0; + } + + ppsTimeType = get_reported_time_type(drSyncUserBootTs, drSyncUserRealTs, ppsFetchTime); + + if (KERNEL_REPORTED_CLOCK_BOOTTIME == ppsTimeType) { + + /*Store PPS kernel time*/ + drsyncKernelTs.tv_sec = ppsFetchTime.tv_sec; + drsyncKernelTs.tv_nsec = ppsFetchTime.tv_nsec; + /*Store User PPS fetch time*/ + drsyncUserTs.tv_sec = drSyncUserBootTs.tv_sec; + drsyncUserTs.tv_nsec = drSyncUserBootTs.tv_nsec; + + LOC_LOGV("[compute_real_to_boot] PPS TimeType CLOCK_BOOTTIME -- report as is"); + retVal = 0; + } else if (KERNEL_REPORTED_CLOCK_REALTIME == ppsTimeType) { + + /* Calculate time difference between REALTIME to BOOT_TIME*/ + calculate_time_difference(drSyncUserRealTs, drSyncUserBootTs, &deltaRealToBootTime); + + /* Calculate the time difference between stored offset and computed one now*/ + calculate_time_difference(time_offset, deltaRealToBootTime, &deltaOffsetTime); + + if ((0 == time_offset.tv_sec && 0 == time_offset.tv_nsec) || + (isTimeOffsetOk(deltaOffsetTime))) { + /* if Time Offset does not change beyond threshold then + ** convert to boot time*/ + drsyncUserTs.tv_sec = drSyncUserBootTs.tv_sec; + drsyncUserTs.tv_nsec = drSyncUserBootTs.tv_nsec; + pps_sync_time_add(ppsFetchTime, deltaRealToBootTime, &drsyncKernelTs); + retVal = 0; + } else { + /*The offset is too high, jump detected in realTime tick, either + ** wall clock changed by user of NTP, skip PPS, re-sync @ next tick + */ + LOC_LOGE("[%s] Jump detected in CLOCK_REALTIME - Offset %ld:%ld", __func__, + deltaOffsetTime.tv_sec, deltaOffsetTime.tv_nsec); + retVal = -1; + } + time_offset.tv_sec = deltaRealToBootTime.tv_sec; + time_offset.tv_nsec = deltaRealToBootTime.tv_nsec; + + LOC_LOGV("[compute_real_to_boot] KernelRealTs %ld:%ld ComputedTs %ld:%ld RealTs %ld:%ld BootTs %ld:%ld Offset %ld:%ld retVal %d ", + ppsFetchTime.tv_sec, ppsFetchTime.tv_nsec, + drsyncKernelTs.tv_sec, drsyncKernelTs.tv_nsec, drSyncUserRealTs.tv_sec, + drSyncUserRealTs.tv_nsec, drsyncUserTs.tv_sec, drsyncUserTs.tv_nsec, + time_offset.tv_sec, time_offset.tv_nsec, retVal); + } else { + LOC_LOGV("[compute_real_to_boot] PPS TimeType Unknown -- KernelTs %ld:%ld userRealTs %ld:%ld userBootTs %ld:%ld", + ppsFetchTime.tv_sec, ppsFetchTime.tv_nsec, + drSyncUserRealTs.tv_sec, drSyncUserRealTs.tv_nsec, + drsyncUserTs.tv_sec, drsyncUserTs.tv_nsec); + retVal = -1; + } + +exit0: + return retVal; + +} + + +/* fetches the timestamp from the PPS source */ +int read_pps(pps_handle *handle) +{ + struct timespec timeout; + pps_info infobuf; + int ret; + static bool isFirstPulseReceived = false; + static unsigned int skipPulseCnt = 0; + // 3sec timeout + timeout.tv_sec = 3; + timeout.tv_nsec = 0; + + ret = pps_fetch(*handle, PPS_TSFMT_TSPEC, &infobuf, &timeout); + + if (ret < 0 && ret !=-EINTR) + { + LOC_LOGV("%s:%d pps_fetch() error %d", __func__, __LINE__, ret); + return -1; + } + if (!isFirstPulseReceived && (skipPPSPulseCnt > 0)) { + skipPulseCnt = skipPPSPulseCnt; + isFirstPulseReceived = true; + LOC_LOGV("%s:%d first pps pulse received %ld (sec) %ld (nsec)", + __func__, __LINE__, infobuf.tv_sec, infobuf.tv_nsec) + }else if (isFirstPulseReceived && (skipPPSPulseCnt > 0) && + ((infobuf.tv_sec - prevDrsyncKernelTs.tv_sec) > gnssOutageInSec)) { + LOC_LOGV("%s:%d long RF outage detected, ignore next %d PPS Pulses", + __func__, __LINE__, skipPPSPulseCnt) + skipPulseCnt = skipPPSPulseCnt; + } + prevDrsyncKernelTs.tv_sec = infobuf.tv_sec; + prevDrsyncKernelTs.tv_nsec = infobuf.tv_nsec; + /* check if this dr sync pulse need to be ignored or not*/ + if (skipPulseCnt > 0) { + LOC_LOGV("%s:%d skip pps count %d, ignoring this pps pulse %ld (sec) %ld (nsec)", + __func__,__LINE__, skipPulseCnt, infobuf.tv_sec, infobuf.tv_nsec); + skipPulseCnt--; + return 0; + } + /* update dr syncpulse time*/ + + pthread_mutex_lock(&ts_lock); + + ret = compute_real_to_boot_time(infobuf); + + pthread_mutex_unlock(&ts_lock); + + return 0; +} + +#ifdef __cplusplus +extern "C" { +#endif +/* infinitely calls read_pps() */ +void *thread_handle(void *input) +{ + int ret; + if(input != NULL) + { + LOC_LOGV("%s:%d Thread Input is present", __func__, __LINE__); + } + while(isActive) + { + ret = read_pps(&handle); + + if (ret == -1 && errno != ETIMEDOUT ) + { + LOC_LOGV("%s:%d Could not fetch PPS source", __func__, __LINE__); + } + } + return NULL; +} + +/* opens the device and fetches from PPS source */ +int initPPS(char *devname) +{ + int ret,pid; + pthread_t thread; + isActive = 1; + + ret = check_device(devname, &handle); + if (ret < 0) + { + LOC_LOGV("%s:%d Could not find PPS source", __func__, __LINE__); + return 0; + } + UTIL_READ_CONF(LOC_PATH_GPS_CONF, gps_conf_param_table); + pthread_mutex_init(&ts_lock,NULL); + + pid = pthread_create(&thread,NULL,&thread_handle,NULL); + if(pid != 0) + { + LOC_LOGV("%s:%d Could not create thread in InitPPS", __func__, __LINE__); + return 0; + } + return 1; +} + +/* stops fetching and closes the device */ +void deInitPPS() +{ + pthread_mutex_lock(&ts_lock); + isActive = 0; + pthread_mutex_unlock(&ts_lock); + + pthread_mutex_destroy(&ts_lock); + pps_destroy(handle); +} + +/* retrieves DRsync kernel timestamp,DRsync userspace timestamp + and updates current timestamp */ +/* Returns: + * 1. @Param out DRsync kernel timestamp + * 2. @Param out DRsync userspace timestamp + * 3. @Param out current timestamp + */ +int getPPS(struct timespec *fineKernelTs ,struct timespec *currentTs, + struct timespec *fineUserTs) +{ + int ret; + + pthread_mutex_lock(&ts_lock); + fineKernelTs->tv_sec = drsyncKernelTs.tv_sec; + fineKernelTs->tv_nsec = drsyncKernelTs.tv_nsec; + + fineUserTs->tv_sec = drsyncUserTs.tv_sec; + fineUserTs->tv_nsec = drsyncUserTs.tv_nsec; + + ret = clock_gettime(CLOCK_BOOTTIME,currentTs); + pthread_mutex_unlock(&ts_lock); + if(ret != 0) + { + LOC_LOGV("%s:%d clock_gettime() error",__func__,__LINE__); + return 0; + } + return 1; +} + +#ifdef __cplusplus +} +#endif + diff --git a/gps/gnsspps/gnsspps.h b/gps/gnsspps/gnsspps.h new file mode 100644 index 0000000..3642f3b --- /dev/null +++ b/gps/gnsspps/gnsspps.h @@ -0,0 +1,45 @@ +/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of The Linux Foundatoin, 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 "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * 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. + */ +#ifndef _GNSSPPS_H +#define _GNSSPPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* opens the device and fetches from PPS source */ +int initPPS(char *devname); +/* updates the fine time stamp */ +int getPPS(struct timespec *current_ts, struct timespec *current_boottime, struct timespec *last_boottime); +/* stops fetching and closes the device */ +void deInitPPS(); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/gps/gnsspps/gnsspps.pc.in b/gps/gnsspps/gnsspps.pc.in new file mode 100644 index 0000000..8931ebd --- /dev/null +++ b/gps/gnsspps/gnsspps.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: gnsspps +Description: QTI GPS gnsspps +Version: @VERSION +Libs: -L${libdir} -lgnsspps +Cflags: -I${includedir}/gnsspps diff --git a/gps/gnsspps/timepps.h b/gps/gnsspps/timepps.h new file mode 100644 index 0000000..fe0d8f0 --- /dev/null +++ b/gps/gnsspps/timepps.h @@ -0,0 +1,106 @@ +/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of The Linux Foundatoin, 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 "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * 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. + */ +#include +#include +#include +#include +#include + +#ifndef _TIMEPPS_H +#define _TIMEPPS_H + +#ifdef __cplusplus +extern "C" { +#endif +/* time of assert event */ +typedef struct timespec pps_info; +/* represents pps source */ +typedef int pps_handle; + + /* Open the PPS source */ +static __inline int pps_create(int source, pps_handle *handle) +{ + int ret; + struct pps_kparams dummy; + + if (!handle) + { + errno = EINVAL; + return -1; + } + /* check if current device is valid pps */ + ret = ioctl(source, PPS_GETPARAMS, &dummy); + if (ret) + { + errno = EOPNOTSUPP; + return -1; + } + *handle = source; + + return 0; +} +/* close the pps source */ +static __inline int pps_destroy(pps_handle handle) +{ + return close(handle); +} +/*reads timestamp from pps device*/ +static __inline int pps_fetch(pps_handle handle, const int tsformat, + pps_info *ppsinfobuf, + const struct timespec *timeout) +{ + struct pps_fdata fdata; + int ret; + + if (tsformat != PPS_TSFMT_TSPEC) + { + errno = EINVAL; + return -1; + } + if (timeout) + { + fdata.timeout.sec = timeout->tv_sec; + fdata.timeout.nsec = timeout->tv_nsec; + fdata.timeout.flags = ~PPS_TIME_INVALID; + } + else + { + fdata.timeout.flags = PPS_TIME_INVALID; + } + ret = ioctl(handle, PPS_FETCH, &fdata); + + ppsinfobuf->tv_sec = fdata.info.assert_tu.sec; + ppsinfobuf->tv_nsec = fdata.info.assert_tu.nsec; + + return ret; +} + +#ifdef __cplusplus +} +#endif +#endif