parent
c3ab03ddcf
commit
eafde3bdb7
@ -0,0 +1,401 @@
|
|||||||
|
/*
|
||||||
|
* linux/kernel/tty_io.c
|
||||||
|
*
|
||||||
|
* (C) 1991 Linus Torvalds
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
|
||||||
|
* or rs-channels. It also implements echoing, cooked mode etc.
|
||||||
|
*
|
||||||
|
* Kill-line thanks to John T Kohl.
|
||||||
|
*/
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#define ALRMMASK (1<<(SIGALRM-1))
|
||||||
|
#define KILLMASK (1<<(SIGKILL-1))
|
||||||
|
#define INTMASK (1<<(SIGINT-1))
|
||||||
|
#define QUITMASK (1<<(SIGQUIT-1))
|
||||||
|
#define TSTPMASK (1<<(SIGTSTP-1))
|
||||||
|
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/tty.h>
|
||||||
|
#include <asm/segment.h>
|
||||||
|
#include <asm/system.h>
|
||||||
|
|
||||||
|
#define _L_FLAG(tty,f) ((tty)->termios.c_lflag & f)
|
||||||
|
#define _I_FLAG(tty,f) ((tty)->termios.c_iflag & f)
|
||||||
|
#define _O_FLAG(tty,f) ((tty)->termios.c_oflag & f)
|
||||||
|
|
||||||
|
#define L_CANON(tty) _L_FLAG((tty),ICANON)
|
||||||
|
#define L_ISIG(tty) _L_FLAG((tty),ISIG)
|
||||||
|
#define L_ECHO(tty) _L_FLAG((tty),ECHO)
|
||||||
|
#define L_ECHOE(tty) _L_FLAG((tty),ECHOE)
|
||||||
|
#define L_ECHOK(tty) _L_FLAG((tty),ECHOK)
|
||||||
|
#define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL)
|
||||||
|
#define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE)
|
||||||
|
|
||||||
|
#define I_UCLC(tty) _I_FLAG((tty),IUCLC)
|
||||||
|
#define I_NLCR(tty) _I_FLAG((tty),INLCR)
|
||||||
|
#define I_CRNL(tty) _I_FLAG((tty),ICRNL)
|
||||||
|
#define I_NOCR(tty) _I_FLAG((tty),IGNCR)
|
||||||
|
|
||||||
|
#define O_POST(tty) _O_FLAG((tty),OPOST)
|
||||||
|
#define O_NLCR(tty) _O_FLAG((tty),ONLCR)
|
||||||
|
#define O_CRNL(tty) _O_FLAG((tty),OCRNL)
|
||||||
|
#define O_NLRET(tty) _O_FLAG((tty),ONLRET)
|
||||||
|
#define O_LCUC(tty) _O_FLAG((tty),OLCUC)
|
||||||
|
|
||||||
|
//鼠标中断处理程序的主体代码(鼠标数据分析)
|
||||||
|
static unsigned char mouse_input_count = 0;
|
||||||
|
//用来记录时鼠标输入的第几个字节的全局变量
|
||||||
|
static unsigned char mouse_left_down;
|
||||||
|
static unsigned char mouse_right_down;
|
||||||
|
static unsigned char mouse_left_move;
|
||||||
|
static unsigned char mouse_down_move;
|
||||||
|
/*......*/
|
||||||
|
static int mouse_x_position;
|
||||||
|
static int mouse_y_position;
|
||||||
|
static int mouse_z_position;
|
||||||
|
|
||||||
|
struct tty_struct tty_table[] = {
|
||||||
|
{
|
||||||
|
{ICRNL, /* change incoming CR to NL */
|
||||||
|
OPOST|ONLCR, /* change outgoing NL to CRNL */
|
||||||
|
0,
|
||||||
|
ISIG | ICANON | ECHO | ECHOCTL | ECHOKE,
|
||||||
|
0, /* console termio */
|
||||||
|
INIT_C_CC},
|
||||||
|
0, /* initial pgrp */
|
||||||
|
0, /* initial stopped */
|
||||||
|
con_write,
|
||||||
|
{0,0,0,0,""}, /* console read-queue */
|
||||||
|
{0,0,0,0,""}, /* console write-queue */
|
||||||
|
{0,0,0,0,""} /* console secondary queue */
|
||||||
|
},{
|
||||||
|
{0, /* no translation */
|
||||||
|
0, /* no translation */
|
||||||
|
B2400 | CS8,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
INIT_C_CC},
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
rs_write,
|
||||||
|
{0x3f8,0,0,0,""}, /* rs 1 */
|
||||||
|
{0x3f8,0,0,0,""},
|
||||||
|
{0,0,0,0,""}
|
||||||
|
},{
|
||||||
|
{0, /* no translation */
|
||||||
|
0, /* no translation */
|
||||||
|
B2400 | CS8,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
INIT_C_CC},
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
rs_write,
|
||||||
|
{0x2f8,0,0,0,""}, /* rs 2 */
|
||||||
|
{0x2f8,0,0,0,""},
|
||||||
|
{0,0,0,0,""}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* these are the tables used by the machine code handlers.
|
||||||
|
* you can implement pseudo-tty's or something by changing
|
||||||
|
* them. Currently not done.
|
||||||
|
*/
|
||||||
|
struct tty_queue * table_list[]={
|
||||||
|
&tty_table[0].read_q, &tty_table[0].write_q,
|
||||||
|
&tty_table[1].read_q, &tty_table[1].write_q,
|
||||||
|
&tty_table[2].read_q, &tty_table[2].write_q
|
||||||
|
};
|
||||||
|
|
||||||
|
void tty_init(void)
|
||||||
|
{
|
||||||
|
rs_init();
|
||||||
|
con_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tty_intr(struct tty_struct * tty, int mask)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (tty->pgrp <= 0)
|
||||||
|
return;
|
||||||
|
for (i=0;i<NR_TASKS;i++)
|
||||||
|
if (task[i] && task[i]->pgrp==tty->pgrp)
|
||||||
|
task[i]->signal |= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sleep_if_empty(struct tty_queue * queue)
|
||||||
|
{
|
||||||
|
cli();
|
||||||
|
while (!current->signal && EMPTY(*queue))
|
||||||
|
interruptible_sleep_on(&queue->proc_list);
|
||||||
|
sti();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sleep_if_full(struct tty_queue * queue)
|
||||||
|
{
|
||||||
|
if (!FULL(*queue))
|
||||||
|
return;
|
||||||
|
cli();
|
||||||
|
while (!current->signal && LEFT(*queue)<128)
|
||||||
|
interruptible_sleep_on(&queue->proc_list);
|
||||||
|
sti();
|
||||||
|
}
|
||||||
|
|
||||||
|
void wait_for_keypress(void)
|
||||||
|
{
|
||||||
|
sleep_if_empty(&tty_table[0].secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_to_cooked(struct tty_struct * tty)
|
||||||
|
{
|
||||||
|
signed char c;
|
||||||
|
|
||||||
|
while (!EMPTY(tty->read_q) && !FULL(tty->secondary)) {
|
||||||
|
GETCH(tty->read_q,c);
|
||||||
|
if (c==13)
|
||||||
|
if (I_CRNL(tty))
|
||||||
|
c=10;
|
||||||
|
else if (I_NOCR(tty))
|
||||||
|
continue;
|
||||||
|
else ;
|
||||||
|
else if (c==10 && I_NLCR(tty))
|
||||||
|
c=13;
|
||||||
|
if (I_UCLC(tty))
|
||||||
|
c=tolower(c);
|
||||||
|
if (L_CANON(tty)) {
|
||||||
|
if (c==KILL_CHAR(tty)) {
|
||||||
|
/* deal with killing the input line */
|
||||||
|
while(!(EMPTY(tty->secondary) ||
|
||||||
|
(c=LAST(tty->secondary))==10 ||
|
||||||
|
c==EOF_CHAR(tty))) {
|
||||||
|
if (L_ECHO(tty)) {
|
||||||
|
if (c<32)
|
||||||
|
PUTCH(127,tty->write_q);
|
||||||
|
PUTCH(127,tty->write_q);
|
||||||
|
tty->write(tty);
|
||||||
|
}
|
||||||
|
DEC(tty->secondary.head);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c==ERASE_CHAR(tty)) {
|
||||||
|
if (EMPTY(tty->secondary) ||
|
||||||
|
(c=LAST(tty->secondary))==10 ||
|
||||||
|
c==EOF_CHAR(tty))
|
||||||
|
continue;
|
||||||
|
if (L_ECHO(tty)) {
|
||||||
|
if (c<32)
|
||||||
|
PUTCH(127,tty->write_q);
|
||||||
|
PUTCH(127,tty->write_q);
|
||||||
|
tty->write(tty);
|
||||||
|
}
|
||||||
|
DEC(tty->secondary.head);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c==STOP_CHAR(tty)) {
|
||||||
|
tty->stopped=1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c==START_CHAR(tty)) {
|
||||||
|
tty->stopped=0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (L_ISIG(tty)) {
|
||||||
|
if (c==INTR_CHAR(tty)) {
|
||||||
|
tty_intr(tty,INTMASK);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c==QUIT_CHAR(tty)) {
|
||||||
|
tty_intr(tty,QUITMASK);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c==10 || c==EOF_CHAR(tty))
|
||||||
|
tty->secondary.data++;
|
||||||
|
if (L_ECHO(tty)) {
|
||||||
|
if (c==10) {
|
||||||
|
PUTCH(10,tty->write_q);
|
||||||
|
PUTCH(13,tty->write_q);
|
||||||
|
} else if (c<32) {
|
||||||
|
if (L_ECHOCTL(tty)) {
|
||||||
|
PUTCH('^',tty->write_q);
|
||||||
|
PUTCH(c+64,tty->write_q);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
PUTCH(c,tty->write_q);
|
||||||
|
tty->write(tty);
|
||||||
|
}
|
||||||
|
PUTCH(c,tty->secondary);
|
||||||
|
}
|
||||||
|
wake_up(&tty->secondary.proc_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tty_read(unsigned channel, char * buf, int nr)
|
||||||
|
{
|
||||||
|
struct tty_struct * tty;
|
||||||
|
char c, * b=buf;
|
||||||
|
int minimum,time,flag=0;
|
||||||
|
long oldalarm;
|
||||||
|
|
||||||
|
if (channel>2 || nr<0) return -1;
|
||||||
|
tty = &tty_table[channel];
|
||||||
|
oldalarm = current->alarm;
|
||||||
|
time = 10L*tty->termios.c_cc[VTIME];
|
||||||
|
minimum = tty->termios.c_cc[VMIN];
|
||||||
|
if (time && !minimum) {
|
||||||
|
minimum=1;
|
||||||
|
if (flag=(!oldalarm || time+jiffies<oldalarm))
|
||||||
|
current->alarm = time+jiffies;
|
||||||
|
}
|
||||||
|
if (minimum>nr)
|
||||||
|
minimum=nr;
|
||||||
|
while (nr>0) {
|
||||||
|
if (flag && (current->signal & ALRMMASK)) {
|
||||||
|
current->signal &= ~ALRMMASK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (current->signal)
|
||||||
|
break;
|
||||||
|
if (EMPTY(tty->secondary) || (L_CANON(tty) &&
|
||||||
|
!tty->secondary.data && LEFT(tty->secondary)>20)) {
|
||||||
|
sleep_if_empty(&tty->secondary);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
GETCH(tty->secondary,c);
|
||||||
|
if (c==EOF_CHAR(tty) || c==10)
|
||||||
|
tty->secondary.data--;
|
||||||
|
if (c==EOF_CHAR(tty) && L_CANON(tty))
|
||||||
|
return (b-buf);
|
||||||
|
else {
|
||||||
|
put_fs_byte(c,b++);
|
||||||
|
if (!--nr)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (nr>0 && !EMPTY(tty->secondary));
|
||||||
|
if (time && !L_CANON(tty))
|
||||||
|
if (flag=(!oldalarm || time+jiffies<oldalarm))
|
||||||
|
current->alarm = time+jiffies;
|
||||||
|
else
|
||||||
|
current->alarm = oldalarm;
|
||||||
|
if (L_CANON(tty)) {
|
||||||
|
if (b-buf)
|
||||||
|
break;
|
||||||
|
} else if (b-buf >= minimum)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
current->alarm = oldalarm;
|
||||||
|
if (current->signal && !(b-buf))
|
||||||
|
return -EINTR;
|
||||||
|
return (b-buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tty_write(unsigned channel, char * buf, int nr)
|
||||||
|
{
|
||||||
|
static cr_flag=0;
|
||||||
|
struct tty_struct * tty;
|
||||||
|
char c, *b=buf;
|
||||||
|
|
||||||
|
if (channel>2 || nr<0) return -1;
|
||||||
|
tty = channel + tty_table;
|
||||||
|
while (nr>0) {
|
||||||
|
sleep_if_full(&tty->write_q);
|
||||||
|
if (current->signal)
|
||||||
|
break;
|
||||||
|
while (nr>0 && !FULL(tty->write_q)) {
|
||||||
|
c=get_fs_byte(b);
|
||||||
|
if (O_POST(tty)) {
|
||||||
|
if (c=='\r' && O_CRNL(tty))
|
||||||
|
c='\n';
|
||||||
|
else if (c=='\n' && O_NLRET(tty))
|
||||||
|
c='\r';
|
||||||
|
if (c=='\n' && !cr_flag && O_NLCR(tty)) {
|
||||||
|
cr_flag = 1;
|
||||||
|
PUTCH(13,tty->write_q);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (O_LCUC(tty))
|
||||||
|
c=toupper(c);
|
||||||
|
}
|
||||||
|
b++; nr--;
|
||||||
|
cr_flag = 0;
|
||||||
|
PUTCH(c,tty->write_q);
|
||||||
|
}
|
||||||
|
tty->write(tty);
|
||||||
|
if (nr>0)
|
||||||
|
schedule();
|
||||||
|
}
|
||||||
|
return (b-buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Jeh, sometimes I really like the 386.
|
||||||
|
* This routine is called from an interrupt,
|
||||||
|
* and there should be absolutely no problem
|
||||||
|
* with sleeping even in an interrupt (I hope).
|
||||||
|
* Of course, if somebody proves me wrong, I'll
|
||||||
|
* hate intel for all time :-). We'll have to
|
||||||
|
* be careful and see to reinstating the interrupt
|
||||||
|
* chips before calling this, though.
|
||||||
|
*
|
||||||
|
* I don't think we sleep here under normal circumstances
|
||||||
|
* anyway, which is good, as the task sleeping might be
|
||||||
|
* totally innocent.
|
||||||
|
*/
|
||||||
|
void do_tty_interrupt(int tty)
|
||||||
|
{
|
||||||
|
copy_to_cooked(tty_table+tty);
|
||||||
|
}
|
||||||
|
|
||||||
|
void chr_dev_init(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void readmouse(int mousecode){
|
||||||
|
if(mousecode == 0xFA)
|
||||||
|
//0xFA是i8042鼠标命令的成功响应的ACK字节
|
||||||
|
{
|
||||||
|
mouse_input_count = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
switch(mouse_input_count)
|
||||||
|
{
|
||||||
|
case 1: //处理第一个字节
|
||||||
|
mouse_left_down = (mousecode&0x1) == 0x1;
|
||||||
|
mouse_right_down = (mousecode&0x2) == 0x2;
|
||||||
|
mouse_left_move = (mousecode&0x10) == 0x10;
|
||||||
|
mouse_down_move = (mousecode&0x20) == 0x20;
|
||||||
|
/*...*/
|
||||||
|
mouse_input_count++;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if(mouse_left_down)
|
||||||
|
/*此时mousecode是一个8位负数的补码表示
|
||||||
|
要将其变为32位需要在前面填充1*/
|
||||||
|
mouse_x_position+=(int)(0xFFFFFF00|mousecode);
|
||||||
|
/* ... */
|
||||||
|
if(mouse_x_position > 100)mouse_x_position = 100; //先设置为100
|
||||||
|
if(mouse_x_position < 0)mouse_x_position = 0;
|
||||||
|
mouse_input_count++;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if(mouse_down_move)
|
||||||
|
mouse_y_position+=(int)(0xFFFFFF00|mousecode);
|
||||||
|
|
||||||
|
if(mouse_y_position > 100)mouse_y_position = 100;
|
||||||
|
if(mouse_y_position < 0)mouse_y_position = 0;
|
||||||
|
mouse_input_count++;
|
||||||
|
break
|
||||||
|
case 4: //滚轮
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue