home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / drivers / char / vc_screen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-15  |  4.5 KB  |  213 lines

  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)
  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)
  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)
  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.     size = vcs_size(inode);
  84.     if (count < 0 || p > size)
  85.         return -EINVAL;
  86.     if (count > size - p)
  87.         count = size - p;
  88.  
  89.     buf0 = buf;
  90.     if (!attr) {
  91.         org = screen_pos(cons, p, viewed);
  92.         while (count-- > 0)
  93.             put_fs_byte(scr_readw(org++) & 0xff, buf++);
  94.     } else {
  95.         if (p < HEADER_SIZE) {
  96.             char header[HEADER_SIZE];
  97.             header[0] = (char) video_num_lines;
  98.             header[1] = (char) video_num_columns;
  99.             getconsxy(cons, header+2);
  100.             while (p < HEADER_SIZE && count-- > 0)
  101.                 put_fs_byte(header[p++], buf++);
  102.         }
  103.         p -= HEADER_SIZE;
  104.         org = screen_pos(cons, p/2, viewed);
  105.         if ((p & 1) && count-- > 0)
  106.             put_fs_byte(scr_readw(org++) >> 8, buf++);
  107.         while (count > 1) {
  108.             put_fs_word(scr_readw(org++), buf);
  109.             buf += 2;
  110.             count -= 2;
  111.         }
  112.         if (count > 0)
  113.             put_fs_byte(scr_readw(org) & 0xff, buf++);
  114.     }
  115.     read = buf - buf0;
  116.     file->f_pos += read;
  117.     return read;
  118. }
  119.  
  120. static int
  121. vcs_write(struct inode *inode, struct file *file, char *buf, int count)
  122. {
  123.     unsigned long p = file->f_pos;
  124.     unsigned int cons = MINOR(inode->i_rdev);
  125.     int viewed, attr, size, written;
  126.     char *buf0;
  127.     unsigned short *org;
  128.  
  129.     attr = (cons & 128);
  130.     cons = (cons & 127);
  131.     if (cons == 0) {
  132.         cons = fg_console;
  133.         viewed = 1;
  134.     } else {
  135.         cons--;
  136.         viewed = 0;
  137.     }
  138.     if (!vc_cons_allocated(cons))
  139.         return -ENXIO;
  140.  
  141.     size = vcs_size(inode);
  142.     if (count < 0 || p > size)
  143.         return -EINVAL;
  144.     if (count > size - p)
  145.         count = size - p;
  146.  
  147.     buf0 = buf;
  148.     if (!attr) {
  149.         org = screen_pos(cons, p, viewed);
  150.         while (count-- > 0) {
  151.             scr_writew((scr_readw(org) & 0xff00) |
  152.                 get_fs_byte(buf++), org);
  153.             org++;
  154.         }
  155.     } else {
  156.         if (p < HEADER_SIZE) {
  157.             char header[HEADER_SIZE];
  158.             getconsxy(cons, header+2);
  159.             while (p < HEADER_SIZE && count-- > 0)
  160.                 header[p++] = get_fs_byte(buf++);
  161.             if (!viewed)
  162.                 putconsxy(cons, header+2);
  163.         }
  164.         p -= HEADER_SIZE;
  165.         org = screen_pos(cons, p/2, viewed);
  166.         if ((p & 1) && count-- > 0) {
  167.             scr_writew((get_fs_byte(buf++) << 8) |
  168.                    (scr_readw(org) & 0xff), org);
  169.             org++;
  170.         }
  171.         while (count > 1) {
  172.             scr_writew(get_fs_word(buf), org++);
  173.             buf += 2;
  174.             count -= 2;
  175.         }
  176.         if (count > 0)
  177.             scr_writew((scr_readw(org) & 0xff00) |
  178.                    get_fs_byte(buf++), org);
  179.     }
  180.     written = buf - buf0;
  181.     file->f_pos += written;
  182.     return written;
  183. }
  184.  
  185. static int
  186. vcs_open(struct inode *inode, struct file *filp)
  187. {
  188.     unsigned int cons = (MINOR(inode->i_rdev) & 127);
  189.     if(cons && !vc_cons_allocated(cons-1))
  190.         return -ENXIO;
  191.     return 0;
  192. }
  193.  
  194. static struct file_operations vcs_fops = {
  195.     vcs_lseek,    /* lseek */
  196.     vcs_read,    /* read */
  197.     vcs_write,    /* write */
  198.     NULL,        /* readdir */
  199.     NULL,        /* select */
  200.     NULL,        /* ioctl */
  201.     NULL,        /* mmap */
  202.     vcs_open,    /* open */
  203.     NULL,        /* release */
  204.     NULL        /* fsync */
  205. };
  206.  
  207. long vcs_init(long kmem_start)
  208. {
  209.     if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops))
  210.         printk("unable to get major %d for vcs device", VCS_MAJOR);
  211.     return kmem_start;
  212. }
  213.