linux/arch/mips/lasat/picvue_proc.c
<<
>>
Prefs
   1/*
   2 * Picvue PVC160206 display driver
   3 *
   4 * Brian Murphy <brian.murphy@eicon.com>
   5 *
   6 */
   7#include <linux/kernel.h>
   8#include <linux/module.h>
   9#include <linux/init.h>
  10#include <linux/errno.h>
  11
  12#include <linux/proc_fs.h>
  13#include <linux/interrupt.h>
  14
  15#include <linux/timer.h>
  16
  17#include "picvue.h"
  18
  19static char pvc_lines[PVC_NLINES][PVC_LINELEN+1];
  20static int pvc_linedata[PVC_NLINES];
  21static struct proc_dir_entry *pvc_display_dir;
  22static char *pvc_linename[PVC_NLINES] = {"line1", "line2"};
  23#define DISPLAY_DIR_NAME "display"
  24static int scroll_dir, scroll_interval;
  25
  26static struct timer_list timer;
  27
  28static void pvc_display(unsigned long data)
  29{
  30        int i;
  31
  32        pvc_clear();
  33        for (i = 0; i < PVC_NLINES; i++)
  34                pvc_write_string(pvc_lines[i], 0, i);
  35}
  36
  37static DECLARE_TASKLET(pvc_display_tasklet, &pvc_display, 0);
  38
  39static int pvc_proc_read_line(char *page, char **start,
  40                             off_t off, int count,
  41                             int *eof, void *data)
  42{
  43        char *origpage = page;
  44        int lineno = *(int *)data;
  45
  46        if (lineno < 0 || lineno > PVC_NLINES) {
  47                printk(KERN_WARNING "proc_read_line: invalid lineno %d\n", lineno);
  48                return 0;
  49        }
  50
  51        down(&pvc_sem);
  52        page += sprintf(page, "%s\n", pvc_lines[lineno]);
  53        up(&pvc_sem);
  54
  55        return page - origpage;
  56}
  57
  58static int pvc_proc_write_line(struct file *file, const char *buffer,
  59                           unsigned long count, void *data)
  60{
  61        int origcount = count;
  62        int lineno = *(int *)data;
  63
  64        if (lineno < 0 || lineno > PVC_NLINES) {
  65                printk(KERN_WARNING "proc_write_line: invalid lineno %d\n",
  66                       lineno);
  67                return origcount;
  68        }
  69
  70        if (count > PVC_LINELEN)
  71                count = PVC_LINELEN;
  72
  73        if (buffer[count-1] == '\n')
  74                count--;
  75
  76        down(&pvc_sem);
  77        strncpy(pvc_lines[lineno], buffer, count);
  78        pvc_lines[lineno][count] = '\0';
  79        up(&pvc_sem);
  80
  81        tasklet_schedule(&pvc_display_tasklet);
  82
  83        return origcount;
  84}
  85
  86static int pvc_proc_write_scroll(struct file *file, const char *buffer,
  87                           unsigned long count, void *data)
  88{
  89        int origcount = count;
  90        int cmd = simple_strtol(buffer, NULL, 10);
  91
  92        down(&pvc_sem);
  93        if (scroll_interval != 0)
  94                del_timer(&timer);
  95
  96        if (cmd == 0) {
  97                scroll_dir = 0;
  98                scroll_interval = 0;
  99        } else {
 100                if (cmd < 0) {
 101                        scroll_dir = -1;
 102                        scroll_interval = -cmd;
 103                } else {
 104                        scroll_dir = 1;
 105                        scroll_interval = cmd;
 106                }
 107                add_timer(&timer);
 108        }
 109        up(&pvc_sem);
 110
 111        return origcount;
 112}
 113
 114static int pvc_proc_read_scroll(char *page, char **start,
 115                             off_t off, int count,
 116                             int *eof, void *data)
 117{
 118        char *origpage = page;
 119
 120        down(&pvc_sem);
 121        page += sprintf(page, "%d\n", scroll_dir * scroll_interval);
 122        up(&pvc_sem);
 123
 124        return page - origpage;
 125}
 126
 127
 128void pvc_proc_timerfunc(unsigned long data)
 129{
 130        if (scroll_dir < 0)
 131                pvc_move(DISPLAY|RIGHT);
 132        else if (scroll_dir > 0)
 133                pvc_move(DISPLAY|LEFT);
 134
 135        timer.expires = jiffies + scroll_interval;
 136        add_timer(&timer);
 137}
 138
 139static void pvc_proc_cleanup(void)
 140{
 141        int i;
 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);
 146
 147        del_timer(&timer);
 148}
 149
 150static int __init pvc_proc_init(void)
 151{
 152        struct proc_dir_entry *proc_entry;
 153        int i;
 154
 155        pvc_display_dir = proc_mkdir(DISPLAY_DIR_NAME, NULL);
 156        if (pvc_display_dir == NULL)
 157                goto error;
 158
 159        for (i = 0; i < PVC_NLINES; i++) {
 160                strcpy(pvc_lines[i], "");
 161                pvc_linedata[i] = i;
 162        }
 163        for (i = 0; i < PVC_NLINES; i++) {
 164                proc_entry = create_proc_entry(pvc_linename[i], 0644,
 165                                               pvc_display_dir);
 166                if (proc_entry == NULL)
 167                        goto error;
 168
 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];
 172        }
 173        proc_entry = create_proc_entry("scroll", 0644, pvc_display_dir);
 174        if (proc_entry == NULL)
 175                goto error;
 176
 177        proc_entry->write_proc = pvc_proc_write_scroll;
 178        proc_entry->read_proc = pvc_proc_read_scroll;
 179
 180        init_timer(&timer);
 181        timer.function = pvc_proc_timerfunc;
 182
 183        return 0;
 184error:
 185        pvc_proc_cleanup();
 186        return -ENOMEM;
 187}
 188
 189module_init(pvc_proc_init);
 190module_exit(pvc_proc_cleanup);
 191MODULE_LICENSE("GPL");
 192