CSAPP LAB4 键盘驱动程序的分析与修改(谢罪)

-------------不用往下看力,,我实验想多了导致画蛇添足,请各位大手子根据实验报告要求编写,在此谢罪-----------------------

.
.
.
.
.
.
.
.
.

  1. 准备环境
  2. Demo
    键盘功能主要由如下几个部分实现:
    keyboard.S:接受键盘中断反馈的键盘码。
    tty_io.c :二级处理输入数据
    console.c :三级处理,之后打印到控制台
    .
    大致流程如下
    keyboards(read/put_queue)------>tty_io(write_queue)—>console(asm)---->屏幕
    .
    按实验提示找到关键文件keyboards.S console.c tty_io.c,后面要做的修改集中于这三个文件之中。运行Bochs模拟器,在按下F头的几个按键之后发现有迫真大量(四行)状态信息输出,影响实验操作,所以先注释掉keyboards.S中第214行对show_stat的调用。
    keyboards.S
    在判断不是F12的语句( cmpb $11, %al ja end_func)后添加call指令,由于没有参数,所以不需要进行其他操作
    在这里插入图片描述
    在console.c中添加如下内容
    在这里插入图片描述
    在下方的con_write函数中添加如下内容,只修改打印到控制台后的状态
    在这里插入图片描述
    cd进入linux-0.11目录,make clean一下,然后重新make,cd …返回上层,输入./run运行模拟器,效果如下
    在这里插入图片描述
    虽然已经实现基本功能,但是按下F12时会有字符L溢出显示,修改如下
    在这里插入图片描述
    即处理F12后立即结束
    此外,也可以全在keyborads interrupt中处理F12事件,注册.global变量后在c中extern引用即可。
    .
  3. Phase1
    实验要求键入F12激活※功能,键入学生姓名拼音,首尾字母等显示※,例如:zhangsan,显示为: ※ha※gsa※
    第二部分的需求的实现比较麻烦,以我的理解来看就是每输入一个字符进行一次判断,先记录坐标和状态,若为合法的拼音声母开头字符则将其记录并加密,若其中插入了非法字符则判断中断,还原显示,直到最后一个合法的韵母结尾为之,结束这一段的更改,其中更新状态也应该被退格键这些按键触发…
    .
    总结一下,先设置一个状态变量status_phase来对操作状态进行判断。当没有输入&完成了一串拼音的加密&由于一些非法字符的输入中断了加密时,这个值置为0。开始正常接收输入时,这个值置为1
    .
    随后,设置两个变量pos_cache&recent_length来控制对缓冲区内容的读取。pos_cache记录最后一次处理开始时的缓冲区内容起始位置,每输入一个字符操作recent_length进行增减后从记录的位置开始一次遍历,先删去输入数量的字符数,再调用__asm__根据缓存重新打印字符到控制台。
    .
    先来看看tty对各种行为的定义
    在这里插入图片描述
    以上定义了tty 等待队列中缓冲区操作宏函数,每一个tty结构中会附带三个tty_queue,发现缓冲区是利用循环队列实现的,在进行操作时并不会直接修改其中队列的缓冲区内存,我们可以利用这一点直接对缓冲区中的内容进行读取,然后在console.c中进行修改,调用csi_p和遍历缓冲区数据并输出到控制台来操作打印出的内容。
    在这里插入图片描述
    根据我的思路主要用到的函数(删除光标处的p个字符)然后在读取并打印内容时选择根据自己设定的偏移量进行读取
    .
    其余可选的还有直接操作x和pos,循环调用del等,这里放一个我的简单实现版本,检测什么的只做了简单的判断,控制按键之类的也没做处理想做处理的话可以根据字符宽度调整startPos的位置与输出策略,输入的内容具体是不是拼音可以写个树做状态机自己体验一下…本人实属一条懒狗 ,大半夜写的逻辑比较乱,总之各位可以运行一下看看笑话,权当抛砖引玉。
    .
    注:按2下F12激活此模式,下图为预览效果:
    在这里插入图片描述
    替换console.c中的con_write及添加部分代码
#define START       0
#define HANDLEING   1
#define EXITED      2

static unsigned char f12Flag = 0;
static unsigned char ph1Flag = 0;

static int 				startedPos 	 = 0;   //record current position
static unsigned char 	status_phase = 0;   //record display status
static int              puttedCnt    = 0;   //record the number of input section
static unsigned char    inited_phase = 0;

void changed_f12Flag(void) {
	f12Flag = ++f12Flag % 2;
	ph1Flag++;
	if(ph1Flag == 2) {
		startedPos = 0;
		status_phase = EXITED;
	}
}

static void print2console(const char c) {
	
	if(!(c>31 && c<127))
		return;

	if (x>=video_num_columns) {
        x -= video_num_columns;
        pos -= video_size_row;
    	lf();
    }
    __asm__("movb attr,%%ah\n\t"
    "movw %%ax,%1\n\t"
    ::"a" (c),"m" (*(short *)pos)
    );
    pos += 2;
    x++;
}


static void printCacheBuffer(struct tty_struct* tty) {
	//restore_cur();
	int k;
	for(k = 0; k < puttedCnt - 1; k++) {
		x--;
		pos -= 2;
		set_cursor();
		//del();
	}
	
	//csi_P(puttedCnt - 1);

	int i = startedPos, j;
	for(j = 0; j < puttedCnt; j++) {

		if(i+j >= TTY_BUF_SIZE)
			j = (i+j) % TTY_BUF_SIZE - i;

		char temp = tty->secondary.buf[i+j];
		
		if(status_phase == HANDLEING) {
			char _begin = tty->secondary.buf[i];
			char _end = tty->secondary.buf[i+puttedCnt - 1];

			if(temp == _begin || temp == _begin - (_begin/97)*32 ||
			   temp == _end   || temp == _end   - (_end/97)*32
			)	
				temp = '*';
		}

		print2console(temp);
	}

	//save_cur();
}

static void phase_1_func(const int cnt, struct tty_struct * tty) {
	switch(status_phase) {
	case START:
		puttedCnt  = cnt;
		break;

	case HANDLEING:
		puttedCnt += cnt;
		break;

	case EXITED:
		startedPos += puttedCnt;
		puttedCnt = cnt;
		break;
	default:
		puttedCnt += cnt;
		break;
	}
	printCacheBuffer(tty);
}

void con_write(struct tty_struct * tty)
{
	int nr;
	char c;

	int pd = 1;

	nr = CHARS(tty->write_q);
	while (nr--) {
		GETCH(tty->write_q,c);
		switch(state) {
			case 0:
				if (c>31 && c<127) {
					if((c>64&&c<91) || (c>96&&c<123)) {
						if(f12Flag)
							c = '*';
						if(ph1Flag) {
							
							if(status_phase == START) {
								status_phase = HANDLEING;
							}
							else if(status_phase == EXITED) {
								
								if(inited_phase)
									startedPos += 1;
								else
									inited_phase = 1;

								status_phase = START;
							}
						}
						
						pd = 0;

					} else if(status_phase == HANDLEING) 
						status_phase = EXITED;

					if(ph1Flag == 2) {
						phase_1_func(1, tty);
					} else {
						startedPos = (++startedPos) % TTY_BUF_SIZE;
						print2console(c);
					}
					
				} else if (c==27)
					state=1;
				else if (c==10 || c==11 || c==12)
					lf();
				else if (c==13)
					cr();
				else if (c==ERASE_CHAR(tty))
					del();
				else if (c==8) {
					if (x) {
						x--;
						pos -= 2;
					}
				} else if (c==9) {
					c=8-(x&7);
					x += c;
					pos += c<<1;
					if (x>video_num_columns) {
						x -= video_num_columns;
						pos -= video_size_row;
						lf();
					}
					c=9;
				} else if (c==7)
					sysbeep();
				break;
			case 1:
				state=0;
				if (c=='[')
					state=2;
				else if (c=='E')
					gotoxy(0,y+1);
				else if (c=='M')
					ri();
				else if (c=='D')
					lf();
				else if (c=='Z')
					respond(tty);
				else if (x=='7')
					save_cur();
				else if (x=='8')
					restore_cur();
				break;
			case 2:
				for(npar=0;npar<NPAR;npar++)
					par[npar]=0;
				npar=0;
				state=3;
				if ((ques=(c=='?')))
					break;
			case 3:
				if (c==';' && npar<NPAR-1) {
					npar++;
					break;
				} else if (c>='0' && c<='9') {
					par[npar]=10*par[npar]+c-'0';
					break;
				} else state=4;
			case 4:
				state=0;
				switch(c) {
					case 'G': case '`':
						if (par[0]) par[0]--;
						gotoxy(par[0],y);
						break;
					case 'A':
						if (!par[0]) par[0]++;
						gotoxy(x,y-par[0]);
						break;
					case 'B': case 'e':
						if (!par[0]) par[0]++;
						gotoxy(x,y+par[0]);
						break;
					case 'C': case 'a':
						if (!par[0]) par[0]++;
						gotoxy(x+par[0],y);
						break;
					case 'D':
						if (!par[0]) par[0]++;
						gotoxy(x-par[0],y);
						break;
					case 'E':
						if (!par[0]) par[0]++;
						gotoxy(0,y+par[0]);
						break;
					case 'F':
						if (!par[0]) par[0]++;
						gotoxy(0,y-par[0]);
						break;
					case 'd':
						if (par[0]) par[0]--;
						gotoxy(x,par[0]);
						break;
					case 'H': case 'f':
						if (par[0]) par[0]--;
						if (par[1]) par[1]--;
						gotoxy(par[1],par[0]);
						break;
					case 'J':
						csi_J(par[0]);
						break;
					case 'K':
						csi_K(par[0]);
						break;
					case 'L':
						csi_L(par[0]);
						break;
					case 'M':
						csi_M(par[0]);
						break;
					case 'P':
						csi_P(par[0]);
						break;
					case '@':
						csi_at(par[0]);
						break;
					case 'm':
						csi_m();
						break;
					case 'r':
						if (par[0]) par[0]--;
						if (!par[1]) par[1] = video_num_lines;
						if (par[0] < par[1] &&
						    par[1] <= video_num_lines) {
							top=par[0];
							bottom=par[1];
						}
						break;
					case 's':
						save_cur();
						break;
					case 'u':
						restore_cur();
						break;
				}
		}
		if(pd) 
			status_phase = EXITED;
	}

	set_cursor();
}
  • 3
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值