timepps.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * timepps.h -- PPS API main header
  3. *
  4. * Copyright (C) 2005-2007 Rodolfo Giometti <giometti@linux.it>
  5. * Copyright (C) 2009-2011 Alexander Gordeev <alex@gordick.net>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * Source: https://github.com/ago/pps-tools/ - Retreived Dec 2013
  18. */
  19. #ifndef _SYS_TIMEPPS_H_
  20. #define _SYS_TIMEPPS_H_
  21. #include <errno.h>
  22. #include <sys/time.h>
  23. #include <sys/ioctl.h>
  24. #include <linux/types.h>
  25. #include <linux/pps.h>
  26. #define LINUXPPS 1 /* signal we are using LinuxPPS */
  27. /*
  28. * New data structures
  29. */
  30. struct ntp_fp {
  31. unsigned int integral;
  32. unsigned int fractional;
  33. };
  34. union pps_timeu {
  35. struct timespec tspec;
  36. struct ntp_fp ntpfp;
  37. unsigned long longpad[3];
  38. };
  39. struct pps_info {
  40. unsigned long assert_sequence; /* seq. num. of assert event */
  41. unsigned long clear_sequence; /* seq. num. of clear event */
  42. union pps_timeu assert_tu; /* time of assert event */
  43. union pps_timeu clear_tu; /* time of clear event */
  44. int current_mode; /* current mode bits */
  45. };
  46. struct pps_params {
  47. int api_version; /* API version # */
  48. int mode; /* mode bits */
  49. union pps_timeu assert_off_tu; /* offset compensation for assert */
  50. union pps_timeu clear_off_tu; /* offset compensation for clear */
  51. };
  52. typedef int pps_handle_t; /* represents a PPS source */
  53. typedef unsigned long pps_seq_t; /* sequence number */
  54. typedef struct ntp_fp ntp_fp_t; /* NTP-compatible time stamp */
  55. typedef union pps_timeu pps_timeu_t; /* generic data type for time stamps */
  56. typedef struct pps_info pps_info_t;
  57. typedef struct pps_params pps_params_t;
  58. #define assert_timestamp assert_tu.tspec
  59. #define clear_timestamp clear_tu.tspec
  60. #define assert_timestamp_ntpfp assert_tu.ntpfp
  61. #define clear_timestamp_ntpfp clear_tu.ntpfp
  62. #define assert_offset assert_off_tu.tspec
  63. #define clear_offset clear_off_tu.tspec
  64. #define assert_offset_ntpfp assert_off_tu.ntpfp
  65. #define clear_offset_ntpfp clear_off_tu.ntpfp
  66. /*
  67. * The PPS API
  68. */
  69. static __inline int time_pps_create(int source, pps_handle_t *handle)
  70. {
  71. int ret;
  72. struct pps_kparams dummy;
  73. if (!handle) {
  74. errno = EINVAL;
  75. return -1;
  76. }
  77. /* First we check if current device is a valid PPS one by
  78. * doing a dummy PPS_GETPARAMS...
  79. */
  80. ret = ioctl(source, PPS_GETPARAMS, &dummy);
  81. if (ret) {
  82. errno = EOPNOTSUPP;
  83. return -1;
  84. }
  85. /* ... then since in LinuxPPS there are no differences between a
  86. * "PPS source" and a "PPS handle", we simply return the same value.
  87. */
  88. *handle = source;
  89. return 0;
  90. }
  91. static __inline int time_pps_destroy(pps_handle_t handle)
  92. {
  93. return close(handle);
  94. }
  95. static __inline int time_pps_getparams(pps_handle_t handle,
  96. pps_params_t *ppsparams)
  97. {
  98. int ret;
  99. struct pps_kparams __ppsparams;
  100. ret = ioctl(handle, PPS_GETPARAMS, &__ppsparams);
  101. ppsparams->api_version = __ppsparams.api_version;
  102. ppsparams->mode = __ppsparams.mode;
  103. ppsparams->assert_off_tu.tspec.tv_sec = __ppsparams.assert_off_tu.sec;
  104. ppsparams->assert_off_tu.tspec.tv_nsec = __ppsparams.assert_off_tu.nsec;
  105. ppsparams->clear_off_tu.tspec.tv_sec = __ppsparams.clear_off_tu.sec;
  106. ppsparams->clear_off_tu.tspec.tv_nsec = __ppsparams.clear_off_tu.nsec;
  107. return ret;
  108. }
  109. static __inline int time_pps_setparams(pps_handle_t handle,
  110. const pps_params_t *ppsparams)
  111. {
  112. struct pps_kparams __ppsparams;
  113. __ppsparams.api_version = ppsparams->api_version;
  114. __ppsparams.mode = ppsparams->mode;
  115. __ppsparams.assert_off_tu.sec = ppsparams->assert_off_tu.tspec.tv_sec;
  116. __ppsparams.assert_off_tu.nsec = ppsparams->assert_off_tu.tspec.tv_nsec;
  117. __ppsparams.clear_off_tu.sec = ppsparams->clear_off_tu.tspec.tv_sec;
  118. __ppsparams.clear_off_tu.nsec = ppsparams->clear_off_tu.tspec.tv_nsec;
  119. return ioctl(handle, PPS_SETPARAMS, &__ppsparams);
  120. }
  121. /* Get capabilities for handle */
  122. static __inline int time_pps_getcap(pps_handle_t handle, int *mode)
  123. {
  124. return ioctl(handle, PPS_GETCAP, mode);
  125. }
  126. static __inline int time_pps_fetch(pps_handle_t handle, const int tsformat,
  127. pps_info_t *ppsinfobuf,
  128. const struct timespec *timeout)
  129. {
  130. struct pps_fdata __fdata;
  131. int ret;
  132. /* Sanity checks */
  133. if (tsformat != PPS_TSFMT_TSPEC) {
  134. errno = EINVAL;
  135. return -1;
  136. }
  137. if (timeout) {
  138. __fdata.timeout.sec = timeout->tv_sec;
  139. __fdata.timeout.nsec = timeout->tv_nsec;
  140. __fdata.timeout.flags = ~PPS_TIME_INVALID;
  141. } else
  142. __fdata.timeout.flags = PPS_TIME_INVALID;
  143. ret = ioctl(handle, PPS_FETCH, &__fdata);
  144. ppsinfobuf->assert_sequence = __fdata.info.assert_sequence;
  145. ppsinfobuf->clear_sequence = __fdata.info.clear_sequence;
  146. ppsinfobuf->assert_tu.tspec.tv_sec = __fdata.info.assert_tu.sec;
  147. ppsinfobuf->assert_tu.tspec.tv_nsec = __fdata.info.assert_tu.nsec;
  148. ppsinfobuf->clear_tu.tspec.tv_sec = __fdata.info.clear_tu.sec;
  149. ppsinfobuf->clear_tu.tspec.tv_nsec = __fdata.info.clear_tu.nsec;
  150. ppsinfobuf->current_mode = __fdata.info.current_mode;
  151. return ret;
  152. }
  153. #ifdef PPS_KC_BIND
  154. static __inline int time_pps_kcbind(pps_handle_t handle,
  155. const int kernel_consumer,
  156. const int edge, const int tsformat)
  157. {
  158. struct pps_bind_args __bind_args;
  159. __bind_args.tsformat = tsformat;
  160. __bind_args.edge = edge;
  161. __bind_args.consumer = kernel_consumer;
  162. return ioctl(handle, PPS_KC_BIND, &__bind_args);
  163. }
  164. #else /* !PPS_KC_BIND */
  165. static __inline int time_pps_kcbind(pps_handle_t handle,
  166. const int kernel_consumer,
  167. const int edge, const int tsformat)
  168. {
  169. /* LinuxPPS doesn't implement kernel consumer feature */
  170. errno = EOPNOTSUPP;
  171. return -1;
  172. }
  173. #endif /* PPS_KC_BIND */
  174. #endif /* _SYS_TIMEPPS_H_ */