Branch oldpackages for 14.07
[14.07/packages.git] / utils / pps-tools / patches / 001-source.patch
1 diff --git a/Makefile b/Makefile
2 new file mode 100644
3 index 0000000..a2660a2
4 --- /dev/null
5 +++ b/Makefile
6 @@ -0,0 +1,27 @@
7 +TARGETS = ppstest ppsctl
8 +
9 +CFLAGS += -Wall -O2 -D_GNU_SOURCE
10 +CFLAGS += -I .
11 +CFLAGS += -ggdb
12 +
13 +# -- Actions section ----------------------------------------------------------
14 +
15 +.PHONY : all depend dep
16 +
17 +all : .depend $(TARGETS)
18 +
19 +.depend depend dep :
20 +       $(CC) $(CFLAGS) -M $(TARGETS:=.c) > .depend
21 +
22 +ifeq (.depend,$(wildcard .depend))
23 +include .depend
24 +endif
25 +
26 +
27 +# -- Clean section ------------------------------------------------------------
28 +
29 +.PHONY : clean
30 +
31 +clean :
32 +       rm -f *.o *~ core .depend
33 +       rm -f ${TARGETS}
34 diff --git a/ppsctl.c b/ppsctl.c
35 new file mode 100644
36 index 0000000..83fd08a
37 --- /dev/null
38 +++ b/ppsctl.c
39 @@ -0,0 +1,62 @@
40 +#include <stdio.h>
41 +#include <unistd.h>
42 +#include <stdlib.h>
43 +#include <errno.h>
44 +#include <sys/ioctl.h>
45 +#include <sys/types.h>
46 +#include <sys/stat.h>
47 +#include <fcntl.h>
48 +#include <string.h>
49 +#include <linux/serial.h>
50 +
51 +void usage(char *name)
52 +{
53 +       fprintf(stderr, "usage: %s <ttyS> [enable|disable]\n", name);
54 +
55 +       exit(EXIT_FAILURE);
56 +}
57 +
58 +int main(int argc, char *argv[])
59 +{
60 +       int fd;
61 +       int ret;
62 +       struct serial_struct ss;
63 +
64 +       if (argc < 2)
65 +               usage(argv[0]);
66 +
67 +       fd = open(argv[1], O_RDWR);
68 +       if (fd < 0) {
69 +               perror("open");
70 +               exit(EXIT_FAILURE);
71 +       }
72 +
73 +       ret = ioctl(fd, TIOCGSERIAL, &ss);
74 +       if (ret < 0) {
75 +               perror("ioctl(TIOCGSERIAL)");
76 +               exit(EXIT_FAILURE);
77 +       }
78 +
79 +       if (argc < 3) {         /* just read PPS status */
80 +               printf("PPS is %sabled\n",
81 +                      ss.flags & ASYNC_HARDPPS_CD ? "en" : "dis");
82 +               exit(EXIT_SUCCESS);
83 +       }
84 +
85 +       if (argv[2][0] == 'e' || argv[2][0] == '1')
86 +               ss.flags |= ASYNC_HARDPPS_CD;
87 +       else if (argv[2][0] == 'd' || argv[2][0] == '0')
88 +               ss.flags &= ~ASYNC_HARDPPS_CD;
89 +       else {
90 +               fprintf(stderr, "invalid state argument \"%s\"\n", argv[2]);
91 +               exit(EXIT_FAILURE);
92 +       }
93 +
94 +       ret = ioctl(fd, TIOCSSERIAL, &ss);
95 +       if (ret < 0) {
96 +               perror("ioctl(TIOCSSERIAL)");
97 +               exit(EXIT_FAILURE);
98 +       }
99 +
100 +       return 0;
101 +}
102 diff --git a/ppsfind b/ppsfind
103 new file mode 100755
104 index 0000000..93c0e17
105 --- /dev/null
106 +++ b/ppsfind
107 @@ -0,0 +1,17 @@
108 +#!/bin/sh
109 +
110 +SYS="/sys/class/pps/"
111 +
112 +if [ $# -lt 1 ] ; then
113 +       echo "usage: ppsfind <name>" >&2
114 +       exit 1
115 +fi
116 +
117 +for d in $(ls $SYS) ; do
118 +       if grep $1 $SYS/$d/name >& /dev/null || \
119 +          grep $1 $SYS/$d/path >& /dev/null ; then
120 +               echo "$d: name=$(cat $SYS/$d/name) path=$(cat $SYS/$d/path)"
121 +       fi
122 +done
123 +
124 +exit 0
125 diff --git a/ppstest.c b/ppstest.c
126 new file mode 100644
127 index 0000000..d125ffa
128 --- /dev/null
129 +++ b/ppstest.c
130 @@ -0,0 +1,151 @@
131 +#include <stdio.h>
132 +#include <stdlib.h>
133 +#include <unistd.h>
134 +#include <errno.h>
135 +#include <string.h>
136 +#include <sys/types.h>
137 +#include <sys/stat.h>
138 +#include <fcntl.h>
139 +
140 +#include <timepps.h>
141 +
142 +int find_source(char *path, pps_handle_t *handle, int *avail_mode)
143 +{
144 +       pps_params_t params;
145 +       int ret;
146 +
147 +       printf("trying PPS source \"%s\"\n", path);
148 +
149 +       /* Try to find the source by using the supplied "path" name */
150 +       ret = open(path, O_RDWR);
151 +       if (ret < 0) {
152 +               fprintf(stderr, "unable to open device \"%s\" (%m)\n", path);
153 +               return ret;
154 +       }
155 +
156 +       /* Open the PPS source (and check the file descriptor) */
157 +       ret = time_pps_create(ret, handle);
158 +       if (ret < 0) {
159 +               fprintf(stderr, "cannot create a PPS source from device "
160 +                               "\"%s\" (%m)\n", path);
161 +               return -1;
162 +       }
163 +       printf("found PPS source \"%s\"\n", path);
164 +
165 +       /* Find out what features are supported */
166 +       ret = time_pps_getcap(*handle, avail_mode);
167 +       if (ret < 0) {
168 +               fprintf(stderr, "cannot get capabilities (%m)\n");
169 +               return -1;
170 +       }
171 +       if ((*avail_mode & PPS_CAPTUREASSERT) == 0) {
172 +               fprintf(stderr, "cannot CAPTUREASSERT\n");
173 +               return -1;
174 +       }
175 +       if ((*avail_mode & PPS_OFFSETASSERT) == 0) {
176 +               fprintf(stderr, "cannot OFFSETASSERT\n");
177 +               return -1;
178 +       }
179 +
180 +       /* Capture assert timestamps, and compensate for a 675 nsec
181 +        * propagation delay */
182 +       ret = time_pps_getparams(*handle, &params);
183 +       if (ret < 0) {
184 +               fprintf(stderr, "cannot get parameters (%m)\n");
185 +               return -1;
186 +       }
187 +       params.assert_offset.tv_sec = 0;
188 +       params.assert_offset.tv_nsec = 675;
189 +       params.mode |= PPS_CAPTUREASSERT | PPS_OFFSETASSERT;
190 +       ret = time_pps_setparams(*handle, &params);
191 +       if (ret < 0) {
192 +               fprintf(stderr, "cannot set parameters (%m)\n");
193 +               return -1;
194 +       }
195 +
196 +       return 0;
197 +}
198 +
199 +int fetch_source(int i, pps_handle_t *handle, int *avail_mode)
200 +{
201 +       struct timespec timeout;
202 +       pps_info_t infobuf;
203 +       int ret;
204 +
205 +       /* create a zero-valued timeout */
206 +       timeout.tv_sec = 3;
207 +       timeout.tv_nsec = 0;
208 +
209 +retry:
210 +       if (*avail_mode & PPS_CANWAIT) /* waits for the next event */
211 +               ret = time_pps_fetch(*handle, PPS_TSFMT_TSPEC, &infobuf,
212 +                                  &timeout);
213 +       else {
214 +               sleep(1);
215 +               ret = time_pps_fetch(*handle, PPS_TSFMT_TSPEC, &infobuf,
216 +                                  &timeout);
217 +       }
218 +       if (ret < 0) {
219 +               if (ret == -EINTR) {
220 +                       fprintf(stderr, "time_pps_fetch() got a signal!\n");
221 +                       goto retry;
222 +               }
223 +
224 +               fprintf(stderr, "time_pps_fetch() error %d (%m)\n", ret);
225 +               return -1;
226 +       }
227 +
228 +       printf("source %d - "
229 +              "assert %ld.%09ld, sequence: %ld - "
230 +              "clear  %ld.%09ld, sequence: %ld\n",
231 +              i,
232 +              infobuf.assert_timestamp.tv_sec,
233 +              infobuf.assert_timestamp.tv_nsec,
234 +              infobuf.assert_sequence,
235 +              infobuf.clear_timestamp.tv_sec,
236 +              infobuf.clear_timestamp.tv_nsec, infobuf.clear_sequence);
237 +
238 +       return 0;
239 +}
240 +
241 +void usage(char *name)
242 +{
243 +       fprintf(stderr, "usage: %s <ppsdev> [<ppsdev> ...]\n", name);
244 +       exit(EXIT_FAILURE);
245 +}
246 +
247 +int main(int argc, char *argv[])
248 +{
249 +       int num;
250 +       pps_handle_t handle[4];
251 +       int avail_mode[4];
252 +       int i = 0;
253 +       int ret;
254 +
255 +       /* Check the command line */
256 +       if (argc < 2)
257 +               usage(argv[0]);
258 +
259 +       for (i = 1; i < argc && i <= 4; i++) {
260 +               ret = find_source(argv[i], &handle[i - 1], &avail_mode[i - 1]);
261 +               if (ret < 0)
262 +                       exit(EXIT_FAILURE);
263 +       }
264 +
265 +       num = i - 1;
266 +       printf("ok, found %d source(s), now start fetching data...\n", num);
267 +
268 +       /* loop, printing the most recent timestamp every second or so */
269 +       while (1) {
270 +               for (i = 0; i < num; i++) {
271 +                       ret = fetch_source(i, &handle[i], &avail_mode[i]);
272 +                       if (ret < 0 && errno != ETIMEDOUT)
273 +                               exit(EXIT_FAILURE);
274 +               }
275 +       }
276 +
277 +       for (; i >= 0; i--)
278 +               time_pps_destroy(handle[i]);
279 +
280 +       return 0;
281 +}
282 diff --git a/timepps.h b/timepps.h
283 new file mode 100644
284 index 0000000..28ebf4c
285 --- /dev/null
286 +++ b/timepps.h
287 @@ -0,0 +1,193 @@
288 +/*
289 + * timepps.h -- PPS API main header
290 + *
291 + * Copyright (C) 2005-2007   Rodolfo Giometti <giometti@linux.it>
292 + *
293 + *   This program is free software; you can redistribute it and/or modify
294 + *   it under the terms of the GNU General Public License as published by
295 + *   the Free Software Foundation; either version 2 of the License, or
296 + *   (at your option) any later version.
297 + *
298 + *   This program is distributed in the hope that it will be useful,
299 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
300 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
301 + *   GNU General Public License for more details.
302 + *
303 + *   You should have received a copy of the GNU General Public License
304 + *   along with this program; if not, write to the Free Software
305 + *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
306 + */
307 +
308 +#ifndef _SYS_TIMEPPS_H_
309 +#define _SYS_TIMEPPS_H_
310 +
311 +#include <sys/syscall.h>
312 +#include <unistd.h>
313 +#include <errno.h>
314 +#include <linux/pps.h>
315 +
316 +/*
317 + * New data structures
318 + */
319 +
320 +struct ntp_fp {
321 +       unsigned int integral;
322 +       unsigned int fractional;
323 +};
324 +
325 +union pps_timeu {
326 +       struct timespec tspec;
327 +       struct ntp_fp ntpfp;
328 +       unsigned long longpad[3];
329 +};
330 +
331 +struct pps_info {
332 +       unsigned long assert_sequence;  /* seq. num. of assert event */
333 +       unsigned long clear_sequence;   /* seq. num. of clear event */
334 +       union pps_timeu assert_tu;      /* time of assert event */
335 +       union pps_timeu clear_tu;       /* time of clear event */
336 +       int current_mode;               /* current mode bits */
337 +};
338 +
339 +struct pps_params {
340 +       int api_version;                /* API version # */
341 +       int mode;                       /* mode bits */
342 +       union pps_timeu assert_off_tu;  /* offset compensation for assert */
343 +       union pps_timeu clear_off_tu;   /* offset compensation for clear */
344 +};
345 +
346 +typedef int pps_handle_t;              /* represents a PPS source */
347 +typedef unsigned long pps_seq_t;       /* sequence number */
348 +typedef struct ntp_fp ntp_fp_t;                /* NTP-compatible time stamp */
349 +typedef union pps_timeu pps_timeu_t;   /* generic data type for time stamps */
350 +typedef struct pps_info pps_info_t;
351 +typedef struct pps_params pps_params_t;
352 +
353 +#define assert_timestamp        assert_tu.tspec
354 +#define clear_timestamp         clear_tu.tspec
355 +
356 +#define assert_timestamp_ntpfp  assert_tu.ntpfp
357 +#define clear_timestamp_ntpfp   clear_tu.ntpfp
358 +
359 +#define assert_offset          assert_off_tu.tspec
360 +#define clear_offset           clear_off_tu.tspec
361 +
362 +#define assert_offset_ntpfp     assert_off_tu.ntpfp
363 +#define clear_offset_ntpfp      clear_off_tu.ntpfp
364 +
365 +/*
366 + * The PPS API
367 + */
368 +
369 +static __inline int time_pps_create(int source, pps_handle_t *handle)
370 +{
371 +       int ret;
372 +
373 +       if (!handle) {
374 +               errno = EINVAL;
375 +               return -1;
376 +       }
377 +
378 +       /* First we check if current device is a PPS valid PPS one...
379 +        */
380 +       ret = ioctl(source, PPS_CHECK);
381 +       if (ret) {
382 +               errno = EOPNOTSUPP;
383 +               return -1;
384 +       }
385 +
386 +       /* ... then since in LinuxPPS there are no differences between a
387 +        * "PPS source" and a "PPS handle", we simply return the same value.
388 +        */
389 +       *handle = source;
390 +
391 +       return 0;
392 +}
393 +
394 +static __inline int time_pps_destroy(pps_handle_t handle)
395 +{
396 +       return close(handle);
397 +}
398 +
399 +static __inline int time_pps_getparams(pps_handle_t handle,
400 +                                       pps_params_t *ppsparams)
401 +{
402 +       int ret;
403 +       struct pps_kparams __ppsparams;
404 +
405 +       ret = ioctl(handle, PPS_GETPARAMS, &__ppsparams);
406 +
407 +       ppsparams->api_version = __ppsparams.api_version;
408 +       ppsparams->mode = __ppsparams.mode;
409 +       ppsparams->assert_off_tu.tspec.tv_sec = __ppsparams.assert_off_tu.sec;
410 +       ppsparams->assert_off_tu.tspec.tv_nsec = __ppsparams.assert_off_tu.nsec;
411 +       ppsparams->clear_off_tu.tspec.tv_sec = __ppsparams.clear_off_tu.sec;
412 +       ppsparams->clear_off_tu.tspec.tv_nsec = __ppsparams.clear_off_tu.nsec;
413 +
414 +       return ret;
415 +}
416 +
417 +static __inline int time_pps_setparams(pps_handle_t handle,
418 +                                       const pps_params_t *ppsparams)
419 +{
420 +       struct pps_kparams __ppsparams;
421 +
422 +       __ppsparams.api_version = ppsparams->api_version;
423 +       __ppsparams.mode = ppsparams->mode;
424 +       __ppsparams.assert_off_tu.sec = ppsparams->assert_off_tu.tspec.tv_sec;
425 +       __ppsparams.assert_off_tu.nsec = ppsparams->assert_off_tu.tspec.tv_nsec;
426 +       __ppsparams.clear_off_tu.sec = ppsparams->clear_off_tu.tspec.tv_sec;
427 +       __ppsparams.clear_off_tu.nsec = ppsparams->clear_off_tu.tspec.tv_nsec;
428 +
429 +       return ioctl(handle, PPS_SETPARAMS, &__ppsparams);
430 +}
431 +
432 +/* Get capabilities for handle */
433 +static __inline int time_pps_getcap(pps_handle_t handle, int *mode)
434 +{
435 +       return ioctl(handle, PPS_GETCAP, mode);
436 +}
437 +
438 +static __inline int time_pps_fetch(pps_handle_t handle, const int tsformat,
439 +                                       pps_info_t *ppsinfobuf,
440 +                                       const struct timespec *timeout)
441 +{
442 +       struct pps_fdata __fdata;
443 +       int ret;
444 +
445 +       /* Sanity checks */
446 +       if (tsformat != PPS_TSFMT_TSPEC) {
447 +               errno = EINVAL;
448 +               return -1;
449 +       }
450 +
451 +       if (timeout) {
452 +               __fdata.timeout.sec = timeout->tv_sec;
453 +               __fdata.timeout.nsec = timeout->tv_nsec;
454 +               __fdata.timeout.flags = ~PPS_TIME_INVALID;
455 +       } else
456 +               __fdata.timeout.flags = PPS_TIME_INVALID;
457 +
458 +       ret = ioctl(handle, PPS_FETCH, &__fdata);
459 +
460 +       ppsinfobuf->assert_sequence = __fdata.info.assert_sequence;
461 +       ppsinfobuf->clear_sequence = __fdata.info.clear_sequence;
462 +       ppsinfobuf->assert_tu.tspec.tv_sec = __fdata.info.assert_tu.sec;
463 +       ppsinfobuf->assert_tu.tspec.tv_nsec = __fdata.info.assert_tu.nsec;
464 +       ppsinfobuf->clear_tu.tspec.tv_sec = __fdata.info.clear_tu.sec;
465 +       ppsinfobuf->clear_tu.tspec.tv_nsec = __fdata.info.clear_tu.nsec;
466 +       ppsinfobuf->current_mode = __fdata.info.current_mode;
467 +
468 +       return ret;
469 +}
470 +
471 +static __inline int time_pps_kcbind(pps_handle_t handle,
472 +                                       const int kernel_consumer,
473 +                                       const int edge, const int tsformat)
474 +{
475 +       /* LinuxPPS doesn't implement kernel consumer feature */
476 +       errno = EOPNOTSUPP;
477 +       return -1;
478 +}
479 +
480 +#endif                         /* _SYS_TIMEPPS_H_ */