194 lines
5.4 KiB
C
Executable file
194 lines
5.4 KiB
C
Executable file
/* 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
|
|
|