summaryrefslogtreecommitdiff
path: root/gps/gnsspps/gnsspps.c
diff options
context:
space:
mode:
Diffstat (limited to 'gps/gnsspps/gnsspps.c')
-rw-r--r--gps/gnsspps/gnsspps.c194
1 files changed, 194 insertions, 0 deletions
diff --git a/gps/gnsspps/gnsspps.c b/gps/gnsspps/gnsspps.c
new file mode 100644
index 0000000..70b23f5
--- /dev/null
+++ b/gps/gnsspps/gnsspps.c
@@ -0,0 +1,194 @@
+/* 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 <log_util.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pthread.h>
+#include <timepps.h>
+#include <linux/types.h>
+
+//DRsync kernel timestamp
+static struct timespec drsyncKernelTs = {0,0};
+//DRsync userspace timestamp
+static struct timespec drsyncUserTs = {0,0};
+//flag to stop fetching timestamp
+static int isActive = 0;
+static pps_handle handle;
+
+static pthread_mutex_t ts_lock;
+
+ /* 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_RDWR);
+ 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;
+}
+
+/* fetches the timestamp from the PPS source */
+int read_pps(pps_handle *handle)
+{
+ struct timespec timeout;
+ pps_info infobuf;
+ int ret;
+ // 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;
+ }
+
+ pthread_mutex_lock(&ts_lock);
+ drsyncKernelTs.tv_sec = infobuf.tv_sec;
+ drsyncKernelTs.tv_nsec = infobuf.tv_nsec;
+ ret = clock_gettime(CLOCK_BOOTTIME,&drsyncUserTs);
+ pthread_mutex_unlock(&ts_lock);
+
+ if(ret != 0)
+ {
+ LOC_LOGV("%s:%d clock_gettime() error",__func__,__LINE__);
+ }
+ 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;
+ }
+
+ 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
+