[Linuxpps] [PATCH] procfs source entries
Rodolfo Giometti
giometti at linux.it
Fri May 26 21:08:16 CEST 2006
Hello,
here a proposal patch to implement a better procfs support.
With this patch you can get in /proc/pps dir one new dir for each PPS source
as follow:
giometti at jeeg:~$ ls /proc/pps/
00/ 01/ 02/ 03/ 04/ sources
giometti at jeeg:~$ cat /proc/pps/sources
id mode echo name path
---- ------ ---- ---------------- ----------------
00 1133 no pps_8250_0 /dev/ttyS0
01 1133 no pps_8250_1 /dev/ttyS1
02 1133 no pps_8250_2 /dev/ttyS2
03 1133 no pps_8250_3 /dev/ttyS3
04 1151 yes ktimer
Then in each dir you have two (or one) new files where you can read
assert/clear events time and number sequence:
giometti at jeeg:~$ cat /proc/pps/04/assert
1148670312.391012000 #166
giometti at jeeg:~$ cat /proc/pps/04/assert
1148670313.391071000 #167
giometti at jeeg:~$ cat /proc/pps/04/assert
1148670313.391071000 #167
giometti at jeeg:~$ cat /proc/pps/04/assert
1148670314.391138000 #168
giometti at jeeg:~$ cat /proc/pps/04/assert
1148670314.391138000 #168
giometti at jeeg:~$ cat /proc/pps/04/assert
1148670315.391247000 #169
Please test ot and report possible bugs/problems.
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/kapi.c b/drivers/pps/kapi.c
index 4f334b9..71177bd 100644
--- a/drivers/pps/kapi.c
+++ b/drivers/pps/kapi.c
@@ -51,7 +51,7 @@ static void linuxpps_add_offeset(struct
int linuxpps_register_source(struct linuxpps_source_info_s *info, int default_params, int try_id)
{
- int i;
+ int i, ret;
if (try_id >= 0) {
if (linuxpps_is_allocated(try_id)) {
@@ -91,6 +91,10 @@ int linuxpps_register_source(struct linu
linuxpps_source[i].params.mode = default_params;
init_waitqueue_head(&linuxpps_source[i].queue);
+ ret = linuxpps_procfs_create_source_entry(info, i);
+ if (ret < 0)
+ err("unable to create procfs entry for source %d", i);
+
return i;
}
@@ -108,6 +112,7 @@ void linuxpps_unregister_source(struct l
}
/* Deallocate the PPS source */
+ linuxpps_procfs_remove_source_entry(info, i);
linuxpps_source[i].info = NULL;
}
diff --git a/drivers/pps/procfs.c b/drivers/pps/procfs.c
index ae6eb1b..49452c5 100644
--- a/drivers/pps/procfs.c
+++ b/drivers/pps/procfs.c
@@ -22,13 +22,44 @@
#include <linux/proc_fs.h>
#include <linux/module.h>
+#include <linux/string.h>
#include <linux/timepps.h>
#include <linux/pps.h>
#ifdef CONFIG_PPS_PROCFS
+/* ----- Global variables --------------------------------------------- */
+
+struct proc_dir_entry *procfs_root_dir;
+
/* ----- Private functions -------------------------------------------- */
+static int linuxpps_procfs_assert_read(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ int len = 0;
+ int id = (int) data;
+ len += sprintf(page+len, "%ld.%ld #%ld\n",
+ linuxpps_source[id].assert_tu.tspec.tv_sec,
+ linuxpps_source[id].assert_tu.tspec.tv_nsec,
+ linuxpps_source[id].assert_sequence);
+
+ *eof = 1;
+ return len;
+}
+
+static int linuxpps_procfs_clear_read(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ int len = 0;
+ int id = (int) data;
+ len += sprintf(page+len, "%ld.%ld #%ld\n",
+ linuxpps_source[id].clear_tu.tspec.tv_sec,
+ linuxpps_source[id].clear_tu.tspec.tv_nsec,
+ linuxpps_source[id].clear_sequence);
+
+ *eof = 1;
+ return len;
+}
+
static int linuxpps_sources_read(char *page, char **start, off_t off, int count, int *eof, void *data)
{
int i;
@@ -38,7 +69,7 @@ static int linuxpps_sources_read(char *p
len += sprintf(page+len, "----\t------\t----\t----------------\t----------------\n");
for (i = 0; i < LINUXPPS_MAX_SOURCES; i++)
if (linuxpps_is_allocated(i))
- len += sprintf(page+len, "%2d\t%4x\t%s\t%s\t\t%s\n",
+ len += sprintf(page+len, "%.02d\t%4x\t%s\t%s\t\t%s\n",
i,
linuxpps_source[i].info->mode,
linuxpps_source[i].info->echo ? "yes" : "no",
@@ -51,6 +82,57 @@ static int linuxpps_sources_read(char *p
/* ----- Public functions --------------------------------------------- */
+void linuxpps_procfs_remove_source_entry(struct linuxpps_source_info_s *info, int id) {
+ char buf[32];
+
+ /* Sanity checks */
+ if (info == NULL || info->dir == NULL || id >= LINUXPPS_MAX_SOURCES)
+ return;
+
+ remove_proc_entry("clear", info->dir);
+ remove_proc_entry("assert", info->dir);
+ sprintf(buf, "%.02d", id);
+ remove_proc_entry(buf, procfs_root_dir);
+}
+
+int linuxpps_procfs_create_source_entry(struct linuxpps_source_info_s *info, int id) {
+ struct proc_dir_entry *procfs_file;
+ char buf[32];
+
+ /* Sanity checks */
+ if (info == NULL || id >= LINUXPPS_MAX_SOURCES)
+ return -EINVAL;
+
+ /* Create dir "/proc/pps/<id>" */
+ sprintf(buf, "%.02d", id);
+ info->dir = proc_mkdir(buf, procfs_root_dir);
+ if (info->dir == NULL)
+ return -ENOMEM;
+
+ /* Create file "assert" and "clear" according to source capability */
+ if (info->mode&PPS_CAPTUREASSERT) {
+ procfs_file = create_proc_entry("assert", S_IRUGO|S_IWUSR, info->dir);
+ if (procfs_file == NULL)
+ goto exit;
+ procfs_file->read_proc = linuxpps_procfs_assert_read;
+ procfs_file->data = (void *) id;
+ }
+ if (info->mode&PPS_CAPTURECLEAR) {
+ procfs_file = create_proc_entry("clear", S_IRUGO|S_IWUSR, info->dir);
+ if (procfs_file == NULL)
+ goto exit;
+ procfs_file->read_proc = linuxpps_procfs_clear_read;
+ procfs_file->data = (void *) id;
+ }
+
+ return 0;
+
+exit :
+ linuxpps_procfs_remove_source_entry(info, id);
+
+ return -ENOMEM;
+}
+
void linuxpps_procfs_unregister(void)
{
remove_proc_entry("pps/sources", NULL);
@@ -61,15 +143,15 @@ void linuxpps_procfs_unregister(void)
int linuxpps_procfs_register(void)
{
- struct proc_dir_entry *root_dir, *procfs_file;
+ struct proc_dir_entry *procfs_file;
/* The root dir in /proc */
- root_dir = proc_mkdir("pps", NULL);
- if (root_dir == NULL)
+ procfs_root_dir = proc_mkdir("pps", NULL);
+ if (procfs_root_dir == NULL)
return -ENOMEM;
/* The file "sources" */
- procfs_file = create_proc_entry("sources", S_IRUGO|S_IWUSR, root_dir);
+ procfs_file = create_proc_entry("sources", S_IRUGO|S_IWUSR, procfs_root_dir);
if (procfs_file == NULL) {
linuxpps_procfs_unregister();
return -ENOMEM;
diff --git a/include/linux/pps.h b/include/linux/pps.h
index 414da07..f6adea0 100644
--- a/include/linux/pps.h
+++ b/include/linux/pps.h
@@ -51,6 +51,9 @@ struct linuxpps_source_info_s {
int mode; /* PPS's allowed mode */
void (*echo)(int source, int event); /* the PPS echo function */
+
+ /* procfs section */
+ struct proc_dir_entry *dir;
};
/* The main struct */
@@ -84,5 +87,7 @@ extern int linuxpps_register_source(stru
extern void linuxpps_unregister_source(struct linuxpps_source_info_s *info);
extern void linuxpps_event(int source, int event);
+extern int linuxpps_procfs_create_source_entry(struct linuxpps_source_info_s *info, int id);
+extern void linuxpps_procfs_remove_source_entry(struct linuxpps_source_info_s *info, int id);
extern int linuxpps_procfs_register(void);
extern void linuxpps_procfs_unregister(void);
More information about the LinuxPPS
mailing list