2 * Picvue PVC160206 display driver
4 * Brian Murphy <brian.murphy@eicon.com>
7 #include <linux/kernel.h>
8 #include <linux/module.h>
9 #include <linux/init.h>
10 #include <linux/errno.h>
12 #include <linux/proc_fs.h>
13 #include <linux/interrupt.h>
15 #include <linux/timer.h>
19 static char pvc_lines
[PVC_NLINES
][PVC_LINELEN
+1];
20 static int pvc_linedata
[PVC_NLINES
];
21 static struct proc_dir_entry
*pvc_display_dir
;
22 static char *pvc_linename
[PVC_NLINES
] = {"line1", "line2"};
23 #define DISPLAY_DIR_NAME "display"
24 static int scroll_dir
, scroll_interval
;
26 static struct timer_list timer
;
28 static void pvc_display(unsigned long data
)
33 for (i
= 0; i
< PVC_NLINES
; i
++)
34 pvc_write_string(pvc_lines
[i
], 0, i
);
37 static DECLARE_TASKLET(pvc_display_tasklet
, &pvc_display
, 0);
39 static int pvc_proc_read_line(char *page
, char **start
,
43 char *origpage
= page
;
44 int lineno
= *(int *)data
;
46 if (lineno
< 0 || lineno
> PVC_NLINES
) {
47 printk(KERN_WARNING
"proc_read_line: invalid lineno %d\n", lineno
);
52 page
+= sprintf(page
, "%s\n", pvc_lines
[lineno
]);
55 return page
- origpage
;
58 static int pvc_proc_write_line(struct file
*file
, const char *buffer
,
59 unsigned long count
, void *data
)
61 int origcount
= count
;
62 int lineno
= *(int *)data
;
64 if (lineno
< 0 || lineno
> PVC_NLINES
) {
65 printk(KERN_WARNING
"proc_write_line: invalid lineno %d\n",
70 if (count
> PVC_LINELEN
)
73 if (buffer
[count
-1] == '\n')
77 strncpy(pvc_lines
[lineno
], buffer
, count
);
78 pvc_lines
[lineno
][count
] = '\0';
81 tasklet_schedule(&pvc_display_tasklet
);
86 static int pvc_proc_write_scroll(struct file
*file
, const char *buffer
,
87 unsigned long count
, void *data
)
89 int origcount
= count
;
90 int cmd
= simple_strtol(buffer
, NULL
, 10);
93 if (scroll_interval
!= 0)
102 scroll_interval
= -cmd
;
105 scroll_interval
= cmd
;
114 static int pvc_proc_read_scroll(char *page
, char **start
,
115 off_t off
, int count
,
116 int *eof
, void *data
)
118 char *origpage
= page
;
121 page
+= sprintf(page
, "%d\n", scroll_dir
* scroll_interval
);
124 return page
- origpage
;
128 void pvc_proc_timerfunc(unsigned long data
)
131 pvc_move(DISPLAY
|RIGHT
);
132 else if (scroll_dir
> 0)
133 pvc_move(DISPLAY
|LEFT
);
135 timer
.expires
= jiffies
+ scroll_interval
;
139 static void pvc_proc_cleanup(void)
142 for (i
= 0; i
< PVC_NLINES
; i
++)
143 remove_proc_entry(pvc_linename
[i
], pvc_display_dir
);
144 remove_proc_entry("scroll", pvc_display_dir
);
145 remove_proc_entry(DISPLAY_DIR_NAME
, NULL
);
150 static int __init
pvc_proc_init(void)
152 struct proc_dir_entry
*proc_entry
;
155 pvc_display_dir
= proc_mkdir(DISPLAY_DIR_NAME
, NULL
);
156 if (pvc_display_dir
== NULL
)
159 for (i
= 0; i
< PVC_NLINES
; i
++) {
160 strcpy(pvc_lines
[i
], "");
163 for (i
= 0; i
< PVC_NLINES
; i
++) {
164 proc_entry
= create_proc_entry(pvc_linename
[i
], 0644,
166 if (proc_entry
== NULL
)
169 proc_entry
->read_proc
= pvc_proc_read_line
;
170 proc_entry
->write_proc
= pvc_proc_write_line
;
171 proc_entry
->data
= &pvc_linedata
[i
];
173 proc_entry
= create_proc_entry("scroll", 0644, pvc_display_dir
);
174 if (proc_entry
== NULL
)
177 proc_entry
->write_proc
= pvc_proc_write_scroll
;
178 proc_entry
->read_proc
= pvc_proc_read_scroll
;
181 timer
.function
= pvc_proc_timerfunc
;
189 module_init(pvc_proc_init
);
190 module_exit(pvc_proc_cleanup
);
191 MODULE_LICENSE("GPL");