root/drivers/char/vc_screen.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vcs_size
  2. vcs_lseek
  3. vcs_read
  4. vcs_write
  5. vcs_open
  6. vcs_init

   1 /*
   2  * linux/drivers/char/vc_screen.c
   3  *
   4  * Provide access to virtual console memory.
   5  * /dev/vcs0: the screen as it is being viewed right now (possibly scrolled)
   6  * /dev/vcsN: the screen of /dev/ttyN (1 <= N <= 63)
   7  *            [minor: N]
   8  *
   9  * /dev/vcsaN: idem, but including attributes, and prefixed with
  10  *      the 4 bytes lines,columns,x,y (as screendump used to give)
  11  *            [minor: N+128]
  12  *
  13  * This replaces screendump and part of selection, so that the system
  14  * administrator can control access using file system permissions.
  15  *
  16  * aeb@cwi.nl - efter Friedas begravelse - 950211
  17  */
  18 
  19 #include <linux/kernel.h>
  20 #include <linux/major.h>
  21 #include <linux/errno.h>
  22 #include <linux/tty.h>
  23 #include <linux/fs.h>
  24 #include <asm/segment.h>
  25 #include "vt_kern.h"
  26 #include "selection.h"
  27 
  28 #define HEADER_SIZE     4
  29 
  30 static inline int
  31 vcs_size(struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  32 {
  33         int size = video_num_lines * video_num_columns;
  34         if (MINOR(inode->i_rdev) & 128)
  35                 size = 2*size + HEADER_SIZE;
  36         return size;
  37 }
  38 
  39 static int
  40 vcs_lseek(struct inode *inode, struct file *file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
  41 {
  42         int size = vcs_size(inode);
  43 
  44         switch (orig) {
  45                 case 0:
  46                         file->f_pos = offset;
  47                         break;
  48                 case 1:
  49                         file->f_pos += offset;
  50                         break;
  51                 case 2:
  52                         file->f_pos = size + offset;
  53                         break;
  54                 default:
  55                         return -EINVAL;
  56         }
  57         if (file->f_pos < 0 || file->f_pos > size)
  58                 return -EINVAL;
  59         return file->f_pos;
  60 }
  61 
  62 static int
  63 vcs_read(struct inode *inode, struct file *file, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  64 {
  65         unsigned long p = file->f_pos;
  66         unsigned int cons = MINOR(inode->i_rdev);
  67         int viewed, attr, size, read;
  68         char *buf0;
  69         unsigned short *org;
  70 
  71         attr = (cons & 128);
  72         cons = (cons & 127);
  73         if (cons == 0) {
  74                 cons = fg_console;
  75                 viewed = 1;
  76         } else {
  77                 cons--;
  78                 viewed = 0;
  79         }
  80         if (!vc_cons_allocated(cons))
  81                 return -ENXIO;
  82 
  83         clear_selection();
  84         size = vcs_size(inode);
  85         if (count < 0 || p > size)
  86                 return -EINVAL;
  87         if (count > size - p)
  88                 count = size - p;
  89 
  90         buf0 = buf;
  91         if (!attr) {
  92                 org = screen_pos(cons, p, viewed);
  93                 while (count-- > 0)
  94                         put_fs_byte(scr_readw(org++) & 0xff, buf++);
  95         } else {
  96                 if (p < HEADER_SIZE) {
  97                         char header[HEADER_SIZE];
  98                         header[0] = (char) video_num_lines;
  99                         header[1] = (char) video_num_columns;
 100                         getconsxy(cons, header+2);
 101                         while (p < HEADER_SIZE && count-- > 0)
 102                             put_fs_byte(header[p++], buf++);
 103                 }
 104                 p -= HEADER_SIZE;
 105                 org = screen_pos(cons, p/2, viewed);
 106                 if ((p & 1) && count-- > 0)
 107                         put_fs_byte(scr_readw(org++) >> 8, buf++);
 108                 while (count > 1) {
 109                         put_fs_word(scr_readw(org++), buf);
 110                         buf += 2;
 111                         count -= 2;
 112                 }
 113                 if (count > 0)
 114                         put_fs_byte(scr_readw(org) & 0xff, buf++);
 115         }
 116         read = buf - buf0;
 117         file->f_pos += read;
 118         return read;
 119 }
 120 
 121 static int
 122 vcs_write(struct inode *inode, struct file *file, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 123 {
 124         unsigned long p = file->f_pos;
 125         unsigned int cons = MINOR(inode->i_rdev);
 126         int viewed, attr, size, written;
 127         char *buf0;
 128         unsigned short *org;
 129 
 130         attr = (cons & 128);
 131         cons = (cons & 127);
 132         if (cons == 0) {
 133                 cons = fg_console;
 134                 viewed = 1;
 135         } else {
 136                 cons--;
 137                 viewed = 0;
 138         }
 139         if (!vc_cons_allocated(cons))
 140                 return -ENXIO;
 141 
 142         clear_selection();
 143         size = vcs_size(inode);
 144         if (count < 0 || p > size)
 145                 return -EINVAL;
 146         if (count > size - p)
 147                 count = size - p;
 148 
 149         buf0 = buf;
 150         if (!attr) {
 151                 org = screen_pos(cons, p, viewed);
 152                 while (count-- > 0) {
 153                         scr_writew((scr_readw(org) & 0xff00) |
 154                                 get_fs_byte(buf++), org);
 155                         org++;
 156                 }
 157         } else {
 158                 if (p < HEADER_SIZE) {
 159                         char header[HEADER_SIZE];
 160                         getconsxy(cons, header+2);
 161                         while (p < HEADER_SIZE && count-- > 0)
 162                                 header[p++] = get_fs_byte(buf++);
 163                         if (!viewed)
 164                                 putconsxy(cons, header+2);
 165                 }
 166                 p -= HEADER_SIZE;
 167                 org = screen_pos(cons, p/2, viewed);
 168                 if ((p & 1) && count-- > 0) {
 169                         scr_writew((get_fs_byte(buf++) << 8) |
 170                                    (scr_readw(org) & 0xff), org);
 171                         org++;
 172                 }
 173                 while (count > 1) {
 174                         scr_writew(get_fs_word(buf), org++);
 175                         buf += 2;
 176                         count -= 2;
 177                 }
 178                 if (count > 0)
 179                         scr_writew((scr_readw(org) & 0xff00) |
 180                                    get_fs_byte(buf++), org);
 181         }
 182         written = buf - buf0;
 183         file->f_pos += written;
 184         return written;
 185 }
 186 
 187 static int
 188 vcs_open(struct inode *inode, struct file *filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 189 {
 190         unsigned int cons = (MINOR(inode->i_rdev) & 127);
 191         if(cons && !vc_cons_allocated(cons-1))
 192                 return -ENXIO;
 193         return 0;
 194 }
 195 
 196 static struct file_operations vcs_fops = {
 197         vcs_lseek,      /* lseek */
 198         vcs_read,       /* read */
 199         vcs_write,      /* write */
 200         NULL,           /* readdir */
 201         NULL,           /* select */
 202         NULL,           /* ioctl */
 203         NULL,           /* mmap */
 204         vcs_open,       /* open */
 205         NULL,           /* release */
 206         NULL            /* fsync */
 207 };
 208 
 209 long vcs_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 210 {
 211         if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops))
 212                 printk("unable to get major %d for vcs device", VCS_MAJOR);
 213         return kmem_start;
 214 }

/* [previous][next][first][last][top][bottom][index][help] */