Module Name:    src
Committed By:   gdt
Date:           Fri Jul 25 16:13:21 UTC 2014

Modified Files:
        src/share/man/man4: ucom.4
        src/sys/dev/usb: ucom.c

Log Message:
Add PPS support to ucom(4).

This is basically cribbed from regular serial ports, and just adds
hooks to call the pps support routines.

Also, note in the ucom(4) man page that there is about 1 ms of
latency.  Discussed on tech-kern in October of 2013, with the only
concern being that someone who didn't know what they were doing might
set up a stratum 1 server, and that somehow might have worse
timekeeping than whatever else that person might have done; the man
page comment is a mitigation for this.

This patch has been live-tested in netbsd-5/i386 and netbsd-6/i386,
and has been running on machines without a USB-serial GPS device for
most of a year with no adverse consequences (very little happens if
the PPS ioctls are not invoked).


To generate a diff of this commit:
cvs rdiff -u -r1.23 -r1.24 src/share/man/man4/ucom.4
cvs rdiff -u -r1.105 -r1.106 src/sys/dev/usb/ucom.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/share/man/man4/ucom.4
diff -u src/share/man/man4/ucom.4:1.23 src/share/man/man4/ucom.4:1.24
--- src/share/man/man4/ucom.4:1.23	Thu Apr 17 17:50:21 2014
+++ src/share/man/man4/ucom.4	Fri Jul 25 16:13:21 2014
@@ -1,4 +1,4 @@
-.\" $NetBSD: ucom.4,v 1.23 2014/04/17 17:50:21 martin Exp $
+.\" $NetBSD: ucom.4,v 1.24 2014/07/25 16:13:21 gdt Exp $
 .\"
 .\" Copyright (c) 1999 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -69,6 +69,12 @@ The
 .Va portno
 locator can be used to decide which port to use for device that have
 multiple external ports.
+.Pp
+Note that while
+.Nm
+supports the (undocumented) pulse-per-second API normally used on
+conventional serial ports, USB serial devices typically have a varying
+latency around 1 ms due to the USB frame structure.
 .Sh FILES
 .Bl -tag -width Pa
 .It Pa /dev/dtyU?

Index: src/sys/dev/usb/ucom.c
diff -u src/sys/dev/usb/ucom.c:1.105 src/sys/dev/usb/ucom.c:1.106
--- src/sys/dev/usb/ucom.c:1.105	Fri Jul 25 08:10:39 2014
+++ src/sys/dev/usb/ucom.c	Fri Jul 25 16:13:21 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: ucom.c,v 1.105 2014/07/25 08:10:39 dholland Exp $	*/
+/*	$NetBSD: ucom.c,v 1.106 2014/07/25 16:13:21 gdt Exp $	*/
 
 /*
  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.105 2014/07/25 08:10:39 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.106 2014/07/25 16:13:21 gdt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -50,6 +50,7 @@ __KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.1
 #include <sys/poll.h>
 #include <sys/queue.h>
 #include <sys/kauth.h>
+#include <sys/timepps.h>
 #include <sys/rnd.h>
 
 #include <dev/usb/usb.h>
@@ -141,6 +142,8 @@ struct ucom_softc {
 	int			sc_refcnt;
 	u_char			sc_dying;	/* disconnecting */
 
+	struct pps_state	sc_pps_state;	/* pps state */
+
 	krndsource_t	sc_rndsource;	/* random source */
 };
 
@@ -418,6 +421,13 @@ ucomopen(dev_t dev, int flag, int mode, 
 
 		ucom_status_change(sc);
 
+		/* Clear PPS capture state on first open. */
+		mutex_spin_enter(&timecounter_lock);
+		memset(&sc->sc_pps_state, 0, sizeof(sc->sc_pps_state));
+		sc->sc_pps_state.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
+		pps_init(&sc->sc_pps_state);
+		mutex_spin_exit(&timecounter_lock);
+
 		/*
 		 * Initialize the termios status to the defaults.  Add in the
 		 * sticky bits from TIOCSFLAGS.
@@ -775,6 +785,20 @@ ucom_do_ioctl(struct ucom_softc *sc, u_l
 		*(int *)data = ucom_to_tiocm(sc);
 		break;
 
+	case PPS_IOC_CREATE:
+	case PPS_IOC_DESTROY:
+	case PPS_IOC_GETPARAMS:
+	case PPS_IOC_SETPARAMS:
+	case PPS_IOC_GETCAP:
+	case PPS_IOC_FETCH:
+#ifdef PPS_SYNC
+	case PPS_IOC_KCBIND:
+#endif
+		mutex_spin_enter(&timecounter_lock);
+		error = pps_ioctl(cmd, data, &sc->sc_pps_state);
+		mutex_spin_exit(&timecounter_lock);
+		break;
+
 	default:
 		error = EPASSTHROUGH;
 		break;
@@ -888,9 +912,18 @@ ucom_status_change(struct ucom_softc *sc
 		old_msr = sc->sc_msr;
 		sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno,
 		    &sc->sc_lsr, &sc->sc_msr);
-		if (ISSET((sc->sc_msr ^ old_msr), UMSR_DCD))
+		if (ISSET((sc->sc_msr ^ old_msr), UMSR_DCD)) {
+			mutex_spin_enter(&timecounter_lock);
+			pps_capture(&sc->sc_pps_state);
+			pps_event(&sc->sc_pps_state,
+			    (sc->sc_msr & UMSR_DCD) ?
+			    PPS_CAPTUREASSERT :
+			    PPS_CAPTURECLEAR);
+			mutex_spin_exit(&timecounter_lock);
+
 			(*tp->t_linesw->l_modem)(tp,
 			    ISSET(sc->sc_msr, UMSR_DCD));
+		}
 	} else {
 		sc->sc_lsr = 0;
 		/* Assume DCD is present, if we have no chance to check it. */

Reply via email to