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>
16 #include <linux/mutex.h>
20 static DEFINE_MUTEX(pvc_mutex
);
21 static char pvc_lines
[PVC_NLINES
][PVC_LINELEN
+1];
22 static int pvc_linedata
[PVC_NLINES
];
23 static struct proc_dir_entry
*pvc_display_dir
;
24 static char *pvc_linename
[PVC_NLINES
] = {"line1", "line2"};
25 #define DISPLAY_DIR_NAME "display"
26 static int scroll_dir
, scroll_interval
;
28 static struct timer_list timer
;
30 static void pvc_display(unsigned long data
)
35 for (i
= 0; i
< PVC_NLINES
; i
++)
36 pvc_write_string(pvc_lines
[i
], 0, i
);
39 static DECLARE_TASKLET(pvc_display_tasklet
, &pvc_display
, 0);
41 static int pvc_proc_read_line(char *page
, char **start
,
45 char *origpage
= page
;
46 int lineno
= *(int *)data
;
48 if (lineno
< 0 || lineno
> PVC_NLINES
) {
49 printk(KERN_WARNING
"proc_read_line: invalid lineno %d\n", lineno
);
53 mutex_lock(&pvc_mutex
);
54 page
+= sprintf(page
, "%s\n", pvc_lines
[lineno
]);
55 mutex_unlock(&pvc_mutex
);
57 return page
- origpage
;
60 static int pvc_proc_write_line(struct file
*file
, const char *buffer
,
61 unsigned long count
, void *data
)
63 int origcount
= count
;
64 int lineno
= *(int *)data
;
66 if (lineno
< 0 || lineno
> PVC_NLINES
) {
67 printk(KERN_WARNING
"proc_write_line: invalid lineno %d\n",
72 if (count
> PVC_LINELEN
)
75 if (buffer
[count
-1] == '\n')
78 mutex_lock(&pvc_mutex
);
79 strncpy(pvc_lines
[lineno
], buffer
, count
);
80 pvc_lines
[lineno
][count
] = '\0';
81 mutex_unlock(&pvc_mutex
);
83 tasklet_schedule(&pvc_display_tasklet
);
88 static int pvc_proc_write_scroll(struct file
*file
, const char *buffer
,
89 unsigned long count
, void *data
)
91 int origcount
= count
;
92 int cmd
= simple_strtol(buffer
, NULL
, 10);
94 mutex_lock(&pvc_mutex
);
95 if (scroll_interval
!= 0)
104 scroll_interval
= -cmd
;
107 scroll_interval
= cmd
;
111 mutex_unlock(&pvc_mutex
);
116 static int pvc_proc_read_scroll(char *page
, char **start
,
117 off_t off
, int count
,
118 int *eof
, void *data
)
120 char *origpage
= page
;
122 mutex_lock(&pvc_mutex
);
123 page
+= sprintf(page
, "%d\n", scroll_dir
* scroll_interval
);
124 mutex_unlock(&pvc_mutex
);
126 return page
- origpage
;
130 void pvc_proc_timerfunc(unsigned long data
)
133 pvc_move(DISPLAY
|RIGHT
);
134 else if (scroll_dir
> 0)
135 pvc_move(DISPLAY
|LEFT
);
137 timer
.expires
= jiffies
+ scroll_interval
;
141 static void pvc_proc_cleanup(void)
144 for (i
= 0; i
< PVC_NLINES
; i
++)
145 remove_proc_entry(pvc_linename
[i
], pvc_display_dir
);
146 remove_proc_entry("scroll", pvc_display_dir
);
147 remove_proc_entry(DISPLAY_DIR_NAME
, NULL
);
152 static int __init
pvc_proc_init(void)
154 struct proc_dir_entry
*proc_entry
;
157 pvc_display_dir
= proc_mkdir(DISPLAY_DIR_NAME
, NULL
);
158 if (pvc_display_dir
== NULL
)
161 for (i
= 0; i
< PVC_NLINES
; i
++) {
162 strcpy(pvc_lines
[i
], "");
165 for (i
= 0; i
< PVC_NLINES
; i
++) {
166 proc_entry
= create_proc_entry(pvc_linename
[i
], 0644,
168 if (proc_entry
== NULL
)
171 proc_entry
->read_proc
= pvc_proc_read_line
;
172 proc_entry
->write_proc
= pvc_proc_write_line
;
173 proc_entry
->data
= &pvc_linedata
[i
];
175 proc_entry
= create_proc_entry("scroll", 0644, pvc_display_dir
);
176 if (proc_entry
== NULL
)
179 proc_entry
->write_proc
= pvc_proc_write_scroll
;
180 proc_entry
->read_proc
= pvc_proc_read_scroll
;
183 timer
.function
= pvc_proc_timerfunc
;
191 module_init(pvc_proc_init
);
192 module_exit(pvc_proc_cleanup
);
193 MODULE_LICENSE("GPL");