/*
 * Program to enable kernel PPS detection on the serial port.
 *
 * Based on a program:
 * Copyright (c) 1996, 1997 by
 * Ulrich Windl <Ulrich.Windl@rz.uni-regensburg.de>
 *
 * By H. Peter Anvin <hpa@zytor.com>
 */

#include <fcntl.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/serial.h>

#ifndef ASYNC_HARDPPS_CD
#define ASYNC_HARDPPS_CD	0x0800	/* Call hardpps when CD goes active */
#endif

#ifndef ASYNC_HARDPPS_INVERT
#define ASYNC_HARDPPS_INVERT    0x2000 /* Some PPS clocks are backwards */
#endif

struct option long_options[] = {
  { "enable", 0, NULL, 'e' },
  { "disable", 0, NULL, 'd' },
  { "inverted", 0, NULL, 'i' },
  { "no-inverted", 0, NULL, 'n' },
  { "verbose", 0, NULL, 'v' },
  { "quiet", 0, NULL, 'q' },
  { 0,0,0,0 }
};

int	main(int argc, char *argv[])
{
	int port_fd;
	struct serial_struct ss;
	int opt;
	char *port;
	int enable = 1;
	int invert = 0;
	int verbose = 0;

	while ( (opt = getopt_long(argc, argv, "edin", long_options, NULL)) != EOF ) {
	  switch (opt) {
	  case 'e':
	    enable = 1;
	    break;
	  case 'd':
	    enable = 0;
	    break;
	  case 'i':
	    invert = 1;
	    break;
	  case 'n':
	    invert = 0;
	    break;
	  case 'v':
	    verbose = 1;
	    break;
	  case 'q':
	    verbose = 0;
	    break;
	  default:
	    fprintf(stderr, "%s: unknown option\n", argv[0]);
	    exit(1);
	  }
	}
	
	if ( argc-optind != 1 ) {
	  fprintf(stderr, "Usage: %s [options] device\n", argv[0]);
	  exit(1);
	}

	port = argv[optind];

	if ( (port_fd = open(port, O_RDWR)) == -1 )
	{
		perror("open");
		exit(1);
	}

	/* set appropriate pps options */

	if ( ioctl(port_fd, TIOCGSERIAL, &ss) == -1 )
	{
		perror("ioctl(TIOCGSERIAL)");
		exit(1);
	}

	if ( enable )
	  ss.flags |= ASYNC_HARDPPS_CD;
	else
	  ss.flags &= ~ASYNC_HARDPPS_CD;

	if ( invert )
	  ss.flags |= ASYNC_HARDPPS_INVERT;
	else
	  ss.flags &= ~ASYNC_HARDPPS_INVERT;

	if ( ioctl(port_fd, TIOCSSERIAL, &ss) == -1 )
	{
		perror("ioctl(TIOCSSERIAL)");
		exit(1);
	}

	if ( verbose ) {
	  printf("%s: kernel PPS %s, polarity %s\n",
		 port,
		 enable ? "enabled" : "disabled",
		 invert ? "inverted" : "normal");
	}

	return(0);
}
