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
= 0, scroll_interval
= 0;
26 static struct timer_list timer
;
28 static void pvc_display(unsigned long data
) {
32 for (i
=0; i
<PVC_NLINES
; i
++)
33 pvc_write_string(pvc_lines
[i
], 0, i
);
36 static DECLARE_TASKLET(pvc_display_tasklet
, &pvc_display
, 0);
38 static int pvc_proc_read_line(char *page
, char **start
,
42 char *origpage
= page
;
43 int lineno
= *(int *)data
;
45 if (lineno
< 0 || lineno
> PVC_NLINES
) {
46 printk("proc_read_line: invalid lineno %d\n", lineno
);
51 page
+= sprintf(page
, "%s\n", pvc_lines
[lineno
]);
54 return page
- origpage
;
57 static int pvc_proc_write_line(struct file
*file
, const char *buffer
,
58 unsigned long count
, void *data
)
60 int origcount
= count
;
61 int lineno
= *(int *)data
;
63 if (lineno
< 0 || lineno
> PVC_NLINES
) {
64 printk("proc_write_line: invalid lineno %d\n", lineno
);
68 if (count
> PVC_LINELEN
)
71 if (buffer
[count
-1] == '\n')
75 strncpy(pvc_lines
[lineno
], buffer
, count
);
76 pvc_lines
[lineno
][count
] = '\0';
79 tasklet_schedule(&pvc_display_tasklet
);
84 static int pvc_proc_write_scroll(struct file
*file
, const char *buffer
,
85 unsigned long count
, void *data
)
87 int origcount
= count
;
88 int cmd
= simple_strtol(buffer
, NULL
, 10);
91 if (scroll_interval
!= 0)
100 scroll_interval
= -cmd
;
103 scroll_interval
= cmd
;
112 static int pvc_proc_read_scroll(char *page
, char **start
,
113 off_t off
, int count
,
114 int *eof
, void *data
)
116 char *origpage
= page
;
119 page
+= sprintf(page
, "%d\n", scroll_dir
* scroll_interval
);
122 return page
- origpage
;
126 void pvc_proc_timerfunc(unsigned long data
)
129 pvc_move(DISPLAY
|RIGHT
);
130 else if (scroll_dir
> 0)
131 pvc_move(DISPLAY
|LEFT
);
133 timer
.expires
= jiffies
+ scroll_interval
;
137 static void pvc_proc_cleanup(void)
140 for (i
=0; i
<PVC_NLINES
; i
++)
141 remove_proc_entry(pvc_linename
[i
], pvc_display_dir
);
142 remove_proc_entry("scroll", pvc_display_dir
);
143 remove_proc_entry(DISPLAY_DIR_NAME
, NULL
);
148 static int __init
pvc_proc_init(void)
150 struct proc_dir_entry
*proc_entry
;
153 pvc_display_dir
= proc_mkdir(DISPLAY_DIR_NAME
, NULL
);
154 if (pvc_display_dir
== NULL
)
157 for (i
=0; i
<PVC_NLINES
; i
++) {
158 strcpy(pvc_lines
[i
], "");
161 for (i
=0; i
<PVC_NLINES
; i
++) {
162 proc_entry
= create_proc_entry(pvc_linename
[i
], 0644, pvc_display_dir
);
163 if (proc_entry
== NULL
)
165 proc_entry
->read_proc
= pvc_proc_read_line
;
166 proc_entry
->write_proc
= pvc_proc_write_line
;
167 proc_entry
->data
= &pvc_linedata
[i
];
169 proc_entry
= create_proc_entry("scroll", 0644, pvc_display_dir
);
170 if (proc_entry
== NULL
)
172 proc_entry
->write_proc
= pvc_proc_write_scroll
;
173 proc_entry
->read_proc
= pvc_proc_read_scroll
;
176 timer
.function
= pvc_proc_timerfunc
;
184 module_init(pvc_proc_init
);
185 module_exit(pvc_proc_cleanup
);
186 MODULE_LICENSE("GPL");