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");