root/drivers/char/pty.c

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

DEFINITIONS

This source file includes following definitions.
  1. pty_close
  2. pty_write
  3. pty_write_room
  4. pty_chars_in_buffer
  5. pty_flush_buffer
  6. pty_open
  7. pty_init

   1 /*
   2  *  linux/kernel/chr_drv/pty.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 /*
   8  *      pty.c
   9  *
  10  * This module exports the following pty function:
  11  * 
  12  *      int  pty_open(struct tty_struct * tty, struct file * filp);
  13  */
  14 
  15 #include <linux/errno.h>
  16 #include <linux/sched.h>
  17 #include <linux/interrupt.h>
  18 #include <linux/tty.h>
  19 #include <linux/tty_flip.h>
  20 #include <linux/fcntl.h>
  21 #include <linux/string.h>
  22 #include <linux/major.h>
  23 
  24 #include <asm/segment.h>
  25 #include <asm/system.h>
  26 #include <asm/bitops.h>
  27 
  28 struct pty_struct {
  29         int     magic;
  30         struct wait_queue * open_wait;
  31 };
  32 
  33 #define PTY_MAGIC 0x5001
  34 
  35 #define PTY_BUF_SIZE 1024
  36 
  37 static unsigned char tmp_buf[PTY_BUF_SIZE];
  38 
  39 struct tty_driver pty_driver, pty_slave_driver;
  40 static int pty_refcount;
  41 
  42 static struct tty_struct *pty_table[NR_PTYS];
  43 static struct termios *pty_termios[NR_PTYS];
  44 static struct termios *pty_termios_locked[NR_PTYS];
  45 static struct tty_struct *ttyp_table[NR_PTYS];
  46 static struct termios *ttyp_termios[NR_PTYS];
  47 static struct termios *ttyp_termios_locked[NR_PTYS];
  48 static struct pty_struct pty_state[NR_PTYS];
  49 
  50 #define MIN(a,b)        ((a) < (b) ? (a) : (b))
  51 
  52 static void pty_close(struct tty_struct * tty, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
  53 {
  54         if (!tty)
  55                 return;
  56         if (tty->driver.subtype == PTY_TYPE_MASTER) {
  57                 if (tty->count > 1)
  58                         printk("master pty_close: count = %d!!\n", tty->count);
  59         } else {
  60                 if (tty->count > 2)
  61                         return;
  62         }
  63         wake_up_interruptible(&tty->read_wait);
  64         wake_up_interruptible(&tty->write_wait);
  65         if (!tty->link)
  66                 return;
  67         wake_up_interruptible(&tty->link->read_wait);
  68         wake_up_interruptible(&tty->link->write_wait);
  69         if (tty->driver.subtype == PTY_TYPE_MASTER)
  70                 tty_hangup(tty->link);
  71         else {
  72                 start_tty(tty);
  73                 set_bit(TTY_SLAVE_CLOSED, &tty->link->flags);
  74         }
  75 }
  76 
  77 static int pty_write(struct tty_struct * tty, int from_user,
     /* [previous][next][first][last][top][bottom][index][help] */
  78                        unsigned char *buf, int count)
  79 {
  80         struct tty_struct *to = tty->link;
  81         int     c, n;
  82 
  83         if (!to || tty->stopped)
  84                 return 0;
  85         
  86         count = MIN(count, to->ldisc.receive_room(to));
  87 
  88         if (from_user) {
  89                 for (c = count; c > 0; c -= n) {
  90                         n = MIN(c, PTY_BUF_SIZE);
  91                         memcpy_fromfs(tmp_buf, buf, n);
  92                         to->ldisc.receive_buf(to, tmp_buf, 0, n);
  93                         buf += n;
  94                 }
  95         } else
  96                 to->ldisc.receive_buf(to, buf, 0, count);
  97         
  98         return count;
  99 }
 100 
 101 static int pty_write_room(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 102 {
 103         struct tty_struct *to = tty->link;
 104 
 105         if (!to || tty->stopped)
 106                 return 0;
 107 
 108         return to->ldisc.receive_room(to);
 109 }
 110 
 111 static int pty_chars_in_buffer(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 112 {
 113         struct tty_struct *to = tty->link;
 114 
 115         if (!to)
 116                 return 0;
 117 
 118         return to->ldisc.chars_in_buffer(to);
 119 }
 120 
 121 static void pty_flush_buffer(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 122 {
 123         struct tty_struct *to = tty->link;
 124         
 125         if (!to)
 126                 return;
 127         
 128         if (to->ldisc.flush_buffer)
 129                 to->ldisc.flush_buffer(to);
 130         
 131         if (to->packet) {
 132                 tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
 133                 wake_up_interruptible(&to->read_wait);
 134         }
 135 }
 136 
 137 int pty_open(struct tty_struct *tty, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 138 {
 139         int     line;
 140         struct  pty_struct *pty;
 141         
 142         if (!tty || !tty->link)
 143                 return -ENODEV;
 144         line = MINOR(tty->device) - tty->driver.minor_start;
 145         if ((line < 0) || (line >= NR_PTYS))
 146                 return -ENODEV;
 147         pty = pty_state + line;
 148         tty->driver_data = pty;
 149         
 150         if (tty->driver.subtype == PTY_TYPE_SLAVE)
 151                 clear_bit(TTY_SLAVE_CLOSED, &tty->link->flags);
 152         wake_up_interruptible(&pty->open_wait);
 153         if (filp->f_flags & O_NDELAY)
 154                 return 0;
 155         while (!tty->link->count && !(current->signal & ~current->blocked))
 156                 interruptible_sleep_on(&pty->open_wait);
 157         if (!tty->link->count)
 158                 return -ERESTARTSYS;
 159         return 0;
 160 }
 161 
 162 long pty_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 163 {
 164         memset(&pty_state, 0, sizeof(pty_state));
 165         memset(&pty_driver, 0, sizeof(struct tty_driver));
 166         pty_driver.magic = TTY_DRIVER_MAGIC;
 167         pty_driver.name = "pty";
 168         pty_driver.major = TTY_MAJOR;
 169         pty_driver.minor_start = 128;
 170         pty_driver.num = NR_PTYS;
 171         pty_driver.type = TTY_DRIVER_TYPE_PTY;
 172         pty_driver.subtype = PTY_TYPE_MASTER;
 173         pty_driver.init_termios = tty_std_termios;
 174         pty_driver.init_termios.c_iflag = 0;
 175         pty_driver.init_termios.c_oflag = 0;
 176         pty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD;
 177         pty_driver.init_termios.c_lflag = 0;
 178         pty_driver.flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW;
 179         pty_driver.refcount = &pty_refcount;
 180         pty_driver.table = pty_table;
 181         pty_driver.termios = pty_termios;
 182         pty_driver.termios_locked = pty_termios_locked;
 183         pty_driver.other = &pty_slave_driver;
 184 
 185         pty_driver.open = pty_open;
 186         pty_driver.close = pty_close;
 187         pty_driver.write = pty_write;
 188         pty_driver.write_room = pty_write_room;
 189         pty_driver.flush_buffer = pty_flush_buffer;
 190         pty_driver.chars_in_buffer = pty_chars_in_buffer;
 191 
 192         pty_slave_driver = pty_driver;
 193         pty_slave_driver.name = "ttyp";
 194         pty_slave_driver.subtype = PTY_TYPE_SLAVE;
 195         pty_slave_driver.minor_start = 192;
 196         pty_slave_driver.init_termios = tty_std_termios;
 197         pty_slave_driver.table = ttyp_table;
 198         pty_slave_driver.termios = ttyp_termios;
 199         pty_slave_driver.termios_locked = ttyp_termios_locked;
 200         pty_slave_driver.other = &pty_driver;
 201 
 202         if (tty_register_driver(&pty_driver))
 203                 panic("Couldn't register pty driver\n");
 204         if (tty_register_driver(&pty_slave_driver))
 205                 panic("Couldn't register pty slave driver\n");
 206         
 207         return kmem_start;
 208 }
 209 
 210         

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