/* * Picvue PVC160206 display driver * * Brian Murphy * */ #include #include #include #include #include #include #include #include "picvue.h" static char pvc_lines[PVC_NLINES][PVC_LINELEN+1]; static int pvc_linedata[PVC_NLINES]; static struct proc_dir_entry *pvc_display_dir; static char *pvc_linename[PVC_NLINES] = {"line1", "line2"}; #define DISPLAY_DIR_NAME "display" static int scroll_dir = 0, scroll_interval = 0; static struct timer_list timer; static void pvc_display(unsigned long data) { int i; pvc_clear(); for (i=0; i PVC_NLINES) { printk("proc_read_line: invalid lineno %d\n", lineno); return 0; } down(&pvc_sem); page += sprintf(page, "%s\n", pvc_lines[lineno]); up(&pvc_sem); return page - origpage; } static int pvc_proc_write_line(struct file *file, const char *buffer, unsigned long count, void *data) { int origcount = count; int lineno = *(int *)data; if (lineno < 0 || lineno > PVC_NLINES) { printk("proc_write_line: invalid lineno %d\n", lineno); return origcount; } if (count > PVC_LINELEN) count = PVC_LINELEN; if (buffer[count-1] == '\n') count--; down(&pvc_sem); strncpy(pvc_lines[lineno], buffer, count); pvc_lines[lineno][count] = '\0'; up(&pvc_sem); tasklet_schedule(&pvc_display_tasklet); return origcount; } static int pvc_proc_write_scroll(struct file *file, const char *buffer, unsigned long count, void *data) { int origcount = count; int cmd = simple_strtol(buffer, NULL, 10); down(&pvc_sem); if (scroll_interval != 0) del_timer(&timer); if (cmd == 0) { scroll_dir = 0; scroll_interval = 0; } else { if (cmd < 0) { scroll_dir = -1; scroll_interval = -cmd; } else { scroll_dir = 1; scroll_interval = cmd; } add_timer(&timer); } up(&pvc_sem); return origcount; } static int pvc_proc_read_scroll(char *page, char **start, off_t off, int count, int *eof, void *data) { char *origpage = page; down(&pvc_sem); page += sprintf(page, "%d\n", scroll_dir * scroll_interval); up(&pvc_sem); return page - origpage; } void pvc_proc_timerfunc(unsigned long data) { if (scroll_dir < 0) pvc_move(DISPLAY|RIGHT); else if (scroll_dir > 0) pvc_move(DISPLAY|LEFT); timer.expires = jiffies + scroll_interval; add_timer(&timer); } static void pvc_proc_cleanup(void) { int i; for (i=0; iread_proc = pvc_proc_read_line; proc_entry->write_proc = pvc_proc_write_line; proc_entry->data = &pvc_linedata[i]; } proc_entry = create_proc_entry("scroll", 0644, pvc_display_dir); if (proc_entry == NULL) goto error; proc_entry->write_proc = pvc_proc_write_scroll; proc_entry->read_proc = pvc_proc_read_scroll; init_timer(&timer); timer.function = pvc_proc_timerfunc; return 0; error: pvc_proc_cleanup(); return -ENOMEM; } module_init(pvc_proc_init); module_exit(pvc_proc_cleanup); MODULE_LICENSE("GPL");