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