Exemple #1
0
/*
 * This is the function called by the virtual terminal subsystem when
 * a key is pressed.
 *
 * The first thing you should do is to pass the character to the line
 * discipline. This way, the character will be buffered, so that when
 * the read system call is made, an entire line will be returned,
 * rather than just a single character.
 *
 * After passing the character off to the line discipline, the result
 * of receive_char() should be echoed to the screen using the
 * tty_echo() function.
 */
void
tty_global_driver_callback(void *arg, char c)
{
        /* DRIVERS {{{ */
        tty_device_t *tty;
        tty_ldisc_t *ldisc;
        tty_driver_t *driver;

        const char *out;

        tty = (tty_device_t *)arg;
        KASSERT(NULL != tty);

        driver = tty->tty_driver;
        KASSERT(NULL != driver);
        KASSERT(NULL != driver->ttd_ops);
        KASSERT(NULL != driver->ttd_ops->provide_char);

        ldisc = tty->tty_ldisc;
        KASSERT(NULL != ldisc);
        KASSERT(NULL != ldisc->ld_ops);
        KASSERT(NULL != ldisc->ld_ops->receive_char);

        out = ldisc->ld_ops->receive_char(ldisc, c);
        tty_echo(driver, out);
        /* DRIVERS }}} */
}
Exemple #2
0
/*
 * This is the function called by the virtual terminal subsystem when
 * a key is pressed.
 *
 * The first thing you should do is to pass the character to the line
 * discipline. This way, the character will be buffered, so that when
 * the read system call is made, an entire line will be returned,drivers/tty/tty.c:51:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'static'

 * rather than just a single character.
 *
 * After passing the character off to the line discipline, the result
 * of receive_char() should be echoed to the screen using the
 * tty_echo() function.
 */
void
tty_global_driver_callback(void *arg, char c)

{
    //tty_device_t * dev = (tty_device_t *)arg;
    char * echo = ((tty_device_t *)arg)->tty_ldisc->ld_ops->receive_char(((tty_device_t *)arg)->tty_ldisc, c);
    tty_echo(((tty_device_t *)arg)->tty_driver, echo);
        NOT_YET_IMPLEMENTED("DRIVERS: tty_global_driver_callback");
}
Exemple #3
0
int caution(void)
{
	int ch;

	printf("these actions will lead to irreparable consequences\n");
	printf("do you want to continue (Y/N) ?");
	fflush(stdout);

	tty_echo(TTY_ECHO_OFF);

	do {
		ch = tolower(getchar());
	} while (ch != 'y' && ch != 'n');

	tty_echo(TTY_ECHO_ON);

	printf(" %c\n", ch);

	return ch == 'y';
}
Exemple #4
0
/*
 * In this function, you should block I/O, process each
 * character with the line discipline and output the result to
 * the driver, and then unblock I/O.
 *
 * Important: You should return the number of bytes processed,
 * _NOT_ the number of bytes written out to the driver.
 */
int
tty_write(bytedev_t *dev, int offset, const void *buf, int count)
{
        /*DRIVERS {{{*/
        void *data;
        tty_device_t *tty;
        tty_ldisc_t *ldisc;
        tty_driver_t *driver;
        int i, nbytes;
        const char *cbuf = (const char *)buf;

        KASSERT(NULL != dev);
        tty = bd_to_tty(dev);

        ldisc = tty->tty_ldisc;
        KASSERT(NULL != ldisc);
        KASSERT(NULL != ldisc->ld_ops);
        KASSERT(NULL != ldisc->ld_ops->process_char);

        driver = tty->tty_driver;
        KASSERT(NULL != driver);
        KASSERT(NULL != driver->ttd_ops);
        KASSERT(NULL != driver->ttd_ops->provide_char);

        data = driver->ttd_ops->block_io(driver);

        nbytes = 0;
        for (i = 0; i < count; ++i) {
                const char *out = ldisc->ld_ops->process_char(ldisc, cbuf[i]);
                ++nbytes;
                tty_echo(driver, out);
        }

        driver->ttd_ops->unblock_io(driver, data);

        return nbytes;
        /*DRIVERS }}}*/

        return 0;
}
Exemple #5
0
 //echo in the kshell will call this
 // call tty_echo
int
tty_write(bytedev_t *dev, int offset, const void *buf, int count)
{

    char * buffer = (char *) buf;
    tty_device_t *tty = bd_to_tty(dev);
    //unit8_t intr = intr_getipl();
    void * data = tty->tty_driver->ttd_ops->block_io(tty->tty_driver);
    int i = 0;
    while(i < count && buffer[i] != '\0'){
        char * tem = tty->tty_ldisc->ld_ops->process_char(tty->tty_ldisc, buffer[i]);
        tty_echo(tty->tty_driver, tem);
        //kfree(tem);
        i++;
    }
    //buf = buffer;
    tty->tty_driver->ttd_ops->unblock_io(tty->tty_driver, data);

        NOT_YET_IMPLEMENTED("DRIVERS: tty_write");

        return 0;
}
Exemple #6
0
static int tty_input(struct tty *t, char ch, unsigned char flag) {
	cc_t *cc = t->termios.c_cc;
	int ignore_cr;
	int raw_mode;
	int is_eol;
	int got_data;

	raw_mode = !TC_L(t, ICANON);

	/* Newline control: IGNCR, ICRNL, INLCR */
	ignore_cr = TC_I(t, IGNCR) && ch == '\r';
	if (!ignore_cr) {
		if (TC_I(t, ICRNL) && ch == '\r') ch = '\n';
		if (TC_I(t, INLCR) && ch == '\n') ch = '\r';
	}
	is_eol = (ch == '\n' || ch == cc[VEOL]);

	if (ignore_cr)
		goto done;

	/* Handle erase/kill */
	if (!raw_mode) {
		int erase_all = (ch == cc[VKILL]);
		if (erase_all || ch == cc[VERASE] || ch == '\b') {

			struct ring edit_ring;
			size_t erase_len = ring_data_size(
						tty_edit_ring(t, &edit_ring), TTY_IO_BUFF_SZ);

			if (erase_len) {
				if (!erase_all)
					erase_len = 1;

				t->i_ring.head -= erase_len - TTY_IO_BUFF_SZ;
				ring_fixup_head(&t->i_ring, TTY_IO_BUFF_SZ);

				while (erase_len--)
					tty_echo_erase(t);
			}

			goto done;
		}
	}

	/* Finally, store and echo the char.
	 *
	 * When i_ring is near to become full, only raw or a line ending chars are
	 * handled. This lets canonical read to see the line with \n or EOL at the
	 * end, even when some chars are missing. */

	if (ring_room_size(&t->i_ring, TTY_IO_BUFF_SZ) > !(raw_mode || is_eol))
		if (ring_write_all_from(&t->i_ring, t->i_buff, TTY_IO_BUFF_SZ, &ch, 1))
			tty_echo(t, ch);

done:
	got_data = (raw_mode || is_eol || ch == cc[VEOF]);

	if (got_data) {
		t->i_canon_ring.head = t->i_ring.head;

		if (raw_mode)
			/* maintain it empty */
			t->i_canon_ring.tail = t->i_canon_ring.head;
	}

	return got_data;
}
Exemple #7
0
int tty_inproc(uint8_t minor, unsigned char c)
{
	unsigned char oc;
	struct termios *td;
	struct s_queue *q = &ttyinq[minor];
	int canon;
	uint16_t pgrp = tty_pgrp[minor];
	uint8_t wr;

	td = &ttydata[minor];
	canon = td->c_lflag & ICANON;

	if (td->c_iflag & ISTRIP)
		c &= 0x7f;	/* Strip off parity */
	if (canon && !c)
		return 1;	/* Simply quit if Null character */

#ifdef CONFIG_IDUMP
	if (c == 0x1a)		/* ^Z */
		idump();	/*   (For debugging) */
#endif
#ifdef CONFIG_MONITOR
	if (c == 0x01)		/* ^A */
		trap_monitor();
#endif

	if (c == '\r' && (td->c_iflag & ICRNL))
		c = '\n';
	if (c == '\n' && (td->c_iflag & INLCR))
		c = '\r';

	if (td->c_lflag & ISIG) {
		if (c == td->c_cc[VINTR]) {	/* ^C */
			sgrpsig(pgrp, SIGINT);
			clrq(q);
			stopflag[minor] = flshflag[minor] = false;
			return 1;
		} else if (c == td->c_cc[VQUIT]) {	/* ^\ */
			sgrpsig(pgrp, SIGQUIT);
			clrq(q);
			stopflag[minor] = flshflag[minor] = false;
			return 1;
		}
	}
	if (c == td->c_cc[VDISCARD]) {	/* ^O */
		flshflag[minor] = !flshflag[minor];
		return 1;
	}
	if (td->c_iflag & IXON) {
		if (c == td->c_cc[VSTOP]) {	/* ^S */
			stopflag[minor] = true;
			return 1;
		}
		if (c == td->c_cc[VSTART]) {	/* ^Q */
			stopflag[minor] = false;
			wakeup(&stopflag[minor]);
			return 1;
		}
	}
	if (canon) {
		if (c == td->c_cc[VERASE]) {
			if (uninsq(q, &oc)) {
				if (oc == '\n' || oc == td->c_cc[VEOL])
					insq(q, oc);	/* Don't erase past nl */
				else if (td->c_lflag & ECHOE)
					tty_erase(minor);
				return 1;
			} else if (c == td->c_cc[VKILL]) {
				while (uninsq(q, &oc)) {
					if (oc == '\n'
					    || oc == td->c_cc[VEOL]) {
						insq(q, oc);	/* Don't erase past nl */
						break;
					}
					if (td->c_lflag & ECHOK)
						tty_erase(minor);
				}
				return 1;
			}
		}
	}

	/* All modes come here */
	if (c == '\n') {
		if ((td->c_oflag & OPOST | ONLCR) == OPOST | ONLCR)
			tty_echo(minor, '\r');
	}

	wr = insq(q, c);
	if (wr)
		tty_echo(minor, c);
	else if (minor < PTY_OFFSET)
		tty_putc_wait(minor, '\007');	/* Beep if no more room */

	if (!canon || c == td->c_cc[VEOL] || c == '\n'
	    || c == td->c_cc[VEOF])
		wakeup(q);
	return wr;
}
Exemple #8
0
/*
 * Process input of a single character received on a tty.
 * echo if required.
 * This may be called with interrupt level.
 */
void tty_input(int c, struct tty *tp)
{
  unsigned char *cc;
  tcflag_t iflag, lflag;
  int sig = -1;

  DPRINTF(TTYDB_CORE, ("tty_input: %d\n", c));

  // Reload power management timer */
  pm_notify(PME_USER_ACTIVITY);

  lflag = tp->t_lflag;
  iflag = tp->t_iflag;
  cc = tp->t_cc;

#if defined(DEBUG) && defined(CONFIG_KD)
  if (c == cc[VDDB]) {
    kd_enter();
    tty_flush(tp, FREAD | FWRITE);
    goto endcase;
  }
#endif /* !CONFIG_KD*/

  /* IGNCR, ICRNL, INLCR */
  if (c == '\r') {
    if (iflag & IGNCR)
      goto endcase;
    else if (iflag & ICRNL)
      c = '\n';
  } else if (c == '\n' && (iflag & INLCR)) {
    c = '\r';
  }

  if (iflag & IXON) {
    /* stop (^S) */
    if (c == cc[VSTOP]) {
      if (!(tp->t_state & TS_TTSTOP)) {
        tp->t_state |= TS_TTSTOP;
        return;
      }
      if (c != cc[VSTART])
        return;
      /* if VSTART == VSTOP then toggle */
      goto endcase;
    }

    /* start (^Q) */
    if (c == cc[VSTART])
      goto restartoutput;
  }

  if (lflag & ICANON) {
    /* erase (^H / ^?) or backspace */
    if (c == cc[VERASE] || c == '\b') {
      if (!ttyq_empty(&tp->t_rawq))
        tty_rubout(tty_unputc(&tp->t_rawq), tp);
      goto endcase;
    }

    /* kill (^U) */
    if (c == cc[VKILL]) {
      while (!ttyq_empty(&tp->t_rawq))
        tty_rubout(tty_unputc(&tp->t_rawq), tp);
      goto endcase;
    }
  }

  if (lflag & ISIG) {
    /* quit (^C) */
    if (c == cc[VINTR] || c == cc[VQUIT]) {
      if (!(lflag & NOFLSH)) {
        tp->t_state |= TS_ISIG;
        tty_flush(tp, FREAD | FWRITE);
      }
      tty_echo(c, tp);
      sig = (c == cc[VINTR]) ? SIGINT : SIGQUIT;
      goto endcase;
    }

    /* suspend (^Z) */
    if (c == cc[VSUSP]) {
      if (!(lflag & NOFLSH)) {
        tp->t_state |= TS_ISIG;
        tty_flush(tp, FREAD | FWRITE);
      }
      tty_echo(c, tp);
      sig = SIGTSTP;
      goto endcase;
    }
  }

  /*
   * Check for input buffer overflow
   */
  if (ttyq_full(&tp->t_rawq)) {
    tty_flush(tp, FREAD | FWRITE);
    goto endcase;
  }

  tty_putc(c, &tp->t_rawq);

  if (lflag & ICANON) {
    if (c == '\n' || c == cc[VEOF] || c == cc[VEOL]) {
      tty_catq(&tp->t_rawq, &tp->t_canq);
      sem_post(&tp->t_input);
    }
  } else {
    sem_post(&tp->t_input);
  }

  if (lflag & ECHO)
    tty_echo(c, tp);

endcase:
  /*
   * IXANY means allow any character to restart output.
   */
  if ((tp->t_state & TS_TTSTOP) && (iflag & IXANY) == 0 &&
      cc[VSTART] != cc[VSTOP])
    return;

restartoutput:
  tp->t_state &= ~TS_TTSTOP;

  if (sig != -1) {
    if (tp->t_pid) {
      tp->t_signo = sig;
      sched_dpc(&tp->t_dpc, &tty_signal, tp);
    }
  }

  tty_start(tp);
}
Exemple #9
0
/* This routine processes a character in response to an interrupt.  It
 * adds the character to the tty input queue, echoing and processing
 * backspace and carriage return.  If the queue contains a full line,
 * it wakes up anything waiting on it.  If it is totally full, it beeps
 * at the user.
 * UZI180 - This routine is called from the raw Hardware read routine,
 * either interrupt or polled, to process the input character.  HFB
 */
int tty_inproc(uint8_t minor, unsigned char c)
{
	unsigned char oc;
	int canon;
	uint8_t wr;
	struct tty *t = &ttydata[minor];
	struct s_queue *q = &ttyinq[minor];

	canon = t->termios.c_lflag & ICANON;

	if (t->termios.c_iflag & ISTRIP)
		c &= 0x7f;	/* Strip off parity */
	if (canon && !c)
		return 1;	/* Simply quit if Null character */

#ifdef CONFIG_IDUMP
	if (c == 0x1a)		/* ^Z */
		idump();	/*   (For debugging) */
#endif
#ifdef CONFIG_MONITOR
	if (c == 0x01)		/* ^A */
		trap_monitor();
#endif

	if (c == '\r' && (t->termios.c_iflag & ICRNL))
		c = '\n';
	if (c == '\n' && (t->termios.c_iflag & INLCR))
		c = '\r';

	if (t->termios.c_lflag & ISIG) {
		if (c == t->termios.c_cc[VINTR]) {	/* ^C */
		        wr = SIGINT;
			goto sigout;
		} else if (c == t->termios.c_cc[VQUIT]) {	/* ^\ */
		        wr = SIGQUIT;
sigout:
			sgrpsig(t->pgrp, wr);
			clrq(q);
			t->flag &= ~(TTYF_STOP | TTYF_DISCARD);
			return 1;
		}
	}
	if (c == t->termios.c_cc[VDISCARD]) {	/* ^O */
	        t->flag ^= TTYF_DISCARD;
		return 1;
	}
	if (t->termios.c_iflag & IXON) {
		if (c == t->termios.c_cc[VSTOP]) {	/* ^S */
		        t->flag |= TTYF_STOP;
			return 1;
		}
		if (c == t->termios.c_cc[VSTART]) {	/* ^Q */
		        t->flag &= ~TTYF_STOP;
			wakeup(&t->flag);
			return 1;
		}
	}
	if (canon) {
		if (c == t->termios.c_cc[VERASE]) {
		        wr = ECHOE;
		        goto eraseout;
		} else if (c == t->termios.c_cc[VKILL]) {
		        wr = ECHOK;
		        goto eraseout;
		}
	}

	/* All modes come here */
	if (c == '\n') {
		if ((t->termios.c_oflag & (OPOST | ONLCR)) == (OPOST | ONLCR))
			tty_echo(minor, '\r');
	}

	wr = insq(q, c);
	if (wr)
		tty_echo(minor, c);
	else
		tty_putc(minor, '\007');	/* Beep if no more room */

	if (!canon || c == t->termios.c_cc[VEOL] || c == '\n'
	    || c == t->termios.c_cc[VEOF])
		wakeup(q);
	return wr;

eraseout:
	while (uninsq(q, &oc)) {
		if (oc == '\n' || oc == t->termios.c_cc[VEOL]) {
			insq(q, oc);	/* Don't erase past nl */
			break;
		}
		if (t->termios.c_lflag & wr)
			tty_erase(minor);
                if (wr == ECHOE)
                        break;
	}
	return 1;
}
Exemple #10
0
/*
 * Process input of a single character received on a tty.
 * echo if required.
 * This may be called with interrupt level.
 */
void
tty_input(int c, struct tty *tp)
{
	unsigned char *cc;
	tcflag_t iflag, lflag;
	int sig = -1;

#ifdef CONFIG_CPUFREQ
	/* Reload power management timer */
	pm_active();
#endif
	lflag = tp->t_lflag;
	iflag = tp->t_iflag;
	cc = tp->t_cc;

	/* IGNCR, ICRNL, INLCR */
	if (c == '\r') {
		if (iflag & IGNCR)
			goto endcase;
		else if (iflag & ICRNL)
			c = '\n';
	} else if (c == '\n' && (iflag & INLCR))
		c = '\r';

	if (iflag & IXON) {
		/* stop (^S) */
		if (c == cc[VSTOP]) {
			if (!(tp->t_state & TS_TTSTOP)) {
				tp->t_state |= TS_TTSTOP;
				return;
			}
			if (c != cc[VSTART])
				return;
			/* if VSTART == VSTOP then toggle */
			goto endcase;
		}
		/* start (^Q) */
		if (c == cc[VSTART])
			goto restartoutput;
	}
	if (lflag & ICANON) {
		/* erase (^H / ^?) or backspace */
		if (c == cc[VERASE] || c == '\b') {
			if (!ttyq_empty(&tp->t_rawq)) {
				ttyq_unputc(&tp->t_rawq);
				tty_rubout(tp);
			}
			goto endcase;
		}
		/* kill (^U) */
		if (c == cc[VKILL]) {
			while (!ttyq_empty(&tp->t_rawq)) {
				ttyq_unputc(&tp->t_rawq);
				tty_rubout(tp);
			}
			goto endcase;
		}
	}
	if (lflag & ISIG) {
		/* quit (^C) */
		if (c == cc[VINTR] || c == cc[VQUIT]) {
			if (!(lflag & NOFLSH))
				tty_flush(tp, FREAD | FWRITE);
			tty_echo(c, tp);
			sig = (c == cc[VINTR]) ? SIGINT : SIGQUIT;
			goto endcase;
		}
		/* suspend (^Z) */
		if (c == cc[VSUSP]) {
			if (!(lflag & NOFLSH))
				tty_flush(tp, FREAD | FWRITE);
			tty_echo(c, tp);
			sig = SIGTSTP;
			goto endcase;
		}
	}

	/*
	 * Check for input buffer overflow
	 */
	if (ttyq_full(&tp->t_rawq)) {
		tty_flush(tp, FREAD | FWRITE);
		goto endcase;
	}
	ttyq_putc(c, &tp->t_rawq);

	if (lflag & ICANON) {
		if (c == '\n' || c == cc[VEOF] || c == cc[VEOL]) {
			tty_catq(&tp->t_rawq, &tp->t_canq);
			sched_wakeup(&tp->t_input);
		}
	} else
		sched_wakeup(&tp->t_input);

	if (lflag & ECHO)
		tty_echo(c, tp);
 endcase:
	/*
	 * IXANY means allow any character to restart output.
	 */
	if ((tp->t_state & TS_TTSTOP) && (iflag & IXANY) == 0 &&
	    cc[VSTART] != cc[VSTOP])
		return;
 restartoutput:
	tp->t_state &= ~TS_TTSTOP;

	if (sig != -1) {
		if (sig_task)
			exception_post(sig_task, sig);
	}
	tty_start(tp);
}
Exemple #11
0
int tty_read(struct inode *inode, struct file *file, char *data, int len)
{
#if 1
    register struct tty *tty = determine_tty(inode->i_rdev);
    register char *pi = 0;
    int j, k;
    int rawmode = (tty->termios.c_lflag & ICANON) ? 0 : 1;
    int blocking = (file->f_flags & O_NONBLOCK) ? 0 : 1;
    unsigned char ch;

    if (len != 0) {
	do {
	    if (tty->ops->read) {
		tty->ops->read(tty);
		blocking = 0;
	    }
	    j = chq_getch(&tty->inq, &ch, blocking);

	    if (j == -1) {
		if (!blocking)
		    break;
		return -EINTR;
	    }
	    if (!rawmode && (j == 04))	/* CTRL-D */
		break;
	    if (rawmode || (j != '\b')) {
		pokeb(current->t_regs.ds, (__u16) (data + ((int)pi)), ch);
		++pi;
		tty_echo(tty, ch);
	    } else if (((int)pi) > 0) {
		--pi;
		k = ((peekb(current->t_regs.ds, (__u16) (data + ((int)pi)))
		      == '\t') ? TAB_SPACES : 1);
		do {
		    tty_echo(tty, ch);
		} while (--k);
	    }
	} while (((int)pi) < len && (rawmode || j != '\n'));
    }
    return (int) pi;


#else
    register struct tty *tty = determine_tty(inode->i_rdev);
    int i = 0, j = 0, k, lch;
    int rawmode = (tty->termios.c_lflag & ICANON) ? 0 : 1;
    int blocking = (file->f_flags & O_NONBLOCK) ? 0 : 1;
    unsigned char ch;

    if (len == 0)
	return 0;

    do {
	if (tty->ops->read) {
	    tty->ops->read(tty);
	    blocking = 0;
	}
	j = chq_getch(&tty->inq, &ch, blocking);

	if (j == -1)
	    if (blocking)
		return -EINTR;
	    else
		break;
	if (!rawmode && (j == 04))	/* CTRL-D */
	    break;
	if (rawmode || (j != '\b')) {
	    pokeb(current->t_regs.ds, (__u16) (data + i++), ch);
	    tty_echo(tty, ch);
	} else if (i > 0) {
	    lch = ((peekb(current->t_regs.ds, (__u16) (data + --i)) == '\t')
			? TAB_SPACES : 1);
	    for (k = 0; k < lch; k++)
		tty_echo(tty, ch);
	}
    } while (i < len && (rawmode || j != '\n'));

    return i;
#endif
}