[LinuxPPS] [PATCH] time_pps_findpath()

Rodolfo Giometti giometti at linux.it
Mon Jun 19 22:25:35 CEST 2006


Hi,

here a patch to add support for new function time_pps_findpath().

You may also find it on GITWeb as branch "dev_time_pps_findpath".

Please refere to testing file "ppstest.c" to know how to use the new
function. However the patch for NTPD driver should look as follow:

  +#ifdef PPS_HAVE_FINDPATH
  +      /* Get the PPS source's real name */
  +      fd = readlink(link, path, STRING_LEN-1);
  +      if (fd <= 0) {
  +              msyslog(LOG_ERR, "refclock: PPS source \"%s\" is not a valid link", PPS_DEVI\CE);
  +              return (1);
  +      }
  +      path[fd] = '\0';
  +
  +      /* Try to find the source */
  +      fd = time_pps_findpath(path, STRING_LEN, id, STRING_LEN);
  +      if (fd < 0) {
  +              msyslog(LOG_ERR, "refclock: cannot find PPS source \"%s\" in the system", PPS_DEVICE);
  +              return (1);
  +      }
  +      msyslog(LOG_INFO, "refclock: found PPS source \"%s\" at id #%d on \"%s\"", PPS_DEVICE, fd, id);
  +#endif   /* PPS_HAVE_FINDPATH */
  +
  +
         if (time_pps_create(fd, &pps_handle) < 0) {
  -              pps_handle = 0;
                 msyslog(LOG_ERR,
                         "refclock: time_pps_create failed: %m");
         }

Define PPS_DEVICE may be init as follow:

   #define PPS_DEVICE	"/dev/pps0"

In this manner we can surely address the right PPS device as show below:

   giometti at jeeg:~/linuxpps$ cat /proc/pps/sources 
   id	mode	echo	name			path
   ----	------	----	----------------	----------------
   00	1151	yes	ktimer		
   01	1133	no	pps_8250_0		/dev/ttyS0
   02	1133	no	pps_8250_1		/dev/ttyS1
   03	1133	no	pps_8250_2		/dev/ttyS2
   04	1133	no	pps_8250_3		/dev/ttyS3
   giometti at jeeg:~/linuxpps/test$ sudo ln -sf /dev/ttyS1 /dev/gps0
   giometti at jeeg:~/linuxpps/test$ sudo ./ppstest /dev/gps0
   found PPS source #2 "pps_8250_1" on "/dev/ttyS1"
   giometti at jeeg:~/linuxpps/test$ sudo ln -sf ktimer /dev/gps0
   giometti at jeeg:~/linuxpps/test$ sudo ./ppstest /dev/gps0
   found PPS source #0 "ktimer" on ""

Note that sources without a "path" can be addressed by "name".

Please, let me know what are think about that.

Ciao,

Rodolfo

-- 

GNU/Linux Solutions                  e-mail:    giometti at enneenne.com
Linux Device Driver                             giometti at gnudd.com
Embedded Systems                     		giometti at linux.it
UNIX programming                     phone:     +39 349 2432127
-------------- next part --------------
diff --git a/drivers/pps/clients/ktimer.c b/drivers/pps/clients/ktimer.c
diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c
index f9ff4c6..2539044 100644
--- a/drivers/pps/pps.c
+++ b/drivers/pps/pps.c
@@ -58,6 +58,24 @@ static inline int linuxpps_find_source(i
 	return i;
 }
 
+static inline int linuxpps_find_path(char *path)
+{
+	int i;
+
+	for (i = 0; i < LINUXPPS_MAX_SOURCES; i++)
+		if (linuxpps_is_allocated(i) &&
+		    (strncmp(linuxpps_source[i].info->path, path,
+			     	LINUXPPS_MAX_NAME_LEN) == 0 ||
+		     strncmp(linuxpps_source[i].info->name, path,
+			     	LINUXPPS_MAX_NAME_LEN) == 0))
+			break;
+
+	if (i >= LINUXPPS_MAX_SOURCES)
+		return -EINVAL;
+
+	return i;
+}
+
 /* --- Input function ------------------------------------------------------ */
 
 static void linuxpps_nl_data_ready(struct sock *sk, int len)
@@ -255,6 +273,25 @@ static void linuxpps_nl_data_ready(struc
 			break;
 	 	}
 
+		case PPS_FIND_PATH : {
+			source = linuxpps_find_path(nlpps->path);
+			if (source < 0) {
+				dbg("no PPS devices found");
+				nlpps->ret = -ENODEV;
+				break;
+		 	}
+
+			/* Found! So copy the info */
+			nlpps->source = source;
+			strncpy(nlpps->name, linuxpps_source[source].info->name,
+				LINUXPPS_MAX_NAME_LEN);
+			strncpy(nlpps->path, linuxpps_source[source].info->path,
+				LINUXPPS_MAX_NAME_LEN);
+			nlpps->ret = 0;
+
+			break;
+	 	}
+
 		default : {
 			/* Unknow command */
 			dbg("unknow command %d", nlpps->cmd);
diff --git a/include/linux/timepps.h b/include/linux/timepps.h
index d623766..499f849 100644
--- a/include/linux/timepps.h
+++ b/include/linux/timepps.h
@@ -153,6 +153,7 @@ struct pps_netlink_msg {
 #define PPS_FETCH		6
 #define PPS_KC_BIND		7
 #define PPS_FIND_SRC		8
+#define PPS_FIND_PATH		9
 
 #ifdef __KERNEL__
 
@@ -451,5 +452,47 @@ static __inline int time_pps_findsource(
 	return nlpps.source;
 }
 
+#define PPS_HAVE_FINDPATH	1
+static __inline int time_pps_findpath(char *path, int pathlen, char *idstring, int idlen)
+{
+	int sock;
+	struct sockaddr_nl src_addr, dest_addr;
+	struct pps_netlink_msg nlpps;
+
+	int ret;
+
+	/* Create the netlink socket */
+	ret = socket(PF_NETLINK, SOCK_RAW, NETLINK_PPSAPI);
+	if (ret < 0)
+		return ret;
+	sock = ret;
+
+	/* Bind the socket with the source address */
+	memset(&src_addr, 0, sizeof(src_addr));
+	src_addr.nl_family = AF_NETLINK;
+	src_addr.nl_pid = getpid();	/* self PID as unique ID */
+	src_addr.nl_groups = 0;		/* not in mcast groups */
+	ret = bind(sock, (struct sockaddr *) &src_addr, sizeof(src_addr));
+	if (ret < 0) {
+		close(sock);
+		return ret;
+	}
+
+	/* Ask the kernel to destroy the PPS source */
+	nlpps.cmd = PPS_FIND_PATH;
+	strncpy(nlpps.path, path, pathlen);
+	ret = netlink_msg(sock, &nlpps);
+	if (ret < 0) {
+		close(sock);
+		return ret;
+	}
+
+	strncpy(path, nlpps.path, pathlen);
+	strncpy(idstring, nlpps.name, idlen);
+
+	close(sock);
+	return nlpps.source;
+}
+
 #endif   /* !__KERNEL__ */
 #endif   /* _SYS_TIMEPPS_H_ */


More information about the LinuxPPS mailing list