reactos操作系统实现(99)

下面来分析键盘的中断处理函数的实现,如下:

#001 BOOLEAN NTAPI

#002 i8042KbdInterruptService(

#003 IN PKINTERRUPT Interrupt,

#004 PVOID Context)

#005 {

#006 PI8042_KEYBOARD_EXTENSION DeviceExtension;

#007 PPORT_DEVICE_EXTENSION PortDeviceExtension;

#008 PKEYBOARD_INPUT_DATA InputData;

#009 ULONG Counter;

#010 UCHAR PortStatus, Output;

#011 BOOLEAN ToReturn = FALSE;

#012 NTSTATUS Status;

#013

这个上下文参数,其实就是设备驱动程序里的设备扩展对象。

#014 DeviceExtension = (PI8042_KEYBOARD_EXTENSION)Context;

这里获取端口扩展属性。

#015 PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension;

计算缓冲区里放入新按键位置。

#016 InputData = DeviceExtension->KeyboardBuffer + DeviceExtension->KeysInBuffer;

读取端口轮询的最大次数。

#017 Counter = PortDeviceExtension->Settings.PollStatusIterations;

#018

#019 while (Counter)

#020 {

通过键盘端口读取状态。

#021 Status = i8042ReadStatus(PortDeviceExtension, &PortStatus);

#022 if (!NT_SUCCESS(Status))

#023 {

#024 WARN_(I8042PRT, "i8042ReadStatus() failed with status 0x%08lx/n", Status);

#025 return FALSE;

#026 }

读取键盘输入的数据。

#027 Status = i8042ReadKeyboardData(PortDeviceExtension, &Output);

#028 if (NT_SUCCESS(Status))

#029 break;

暂停一会再进入下一次尝试读取。

#030 KeStallExecutionProcessor(1);

#031 Counter--;

#032 }

轮询次数计数为0,那么说明读取键盘硬件失败。

#033 if (Counter == 0)

#034 {

#035 WARN_(I8042PRT, "Spurious i8042 keyboard interrupt/n");

#036 return FALSE;

#037 }

#038

#039 INFO_(I8042PRT, "Got: 0x%02x/n", Output);

#040

判断是否是CTRL + SCROLL组合键。

#041 if (PortDeviceExtension->Settings.CrashOnCtrlScroll)

#042 {

#043 /* Test for CTRL + SCROLL LOCK twice */

#044 static const UCHAR ScanCodes[] = { 0xe0, 0x1d, 0x46, 0xc6, 0x46, 0 };

#045

#046 if (Output == ScanCodes[DeviceExtension->ComboPosition])

#047 {

#048 DeviceExtension->ComboPosition++;

#049 if (ScanCodes[DeviceExtension->ComboPosition] == 0)

#050 KeBugCheck(MANUALLY_INITIATED_CRASH);

#051 }

#052 else if (Output == ScanCodes[0])

#053 DeviceExtension->ComboPosition = 1;

#054 else

#055 DeviceExtension->ComboPosition = 0;

#056 }

#057

调用ISR的回调函数,如果已经处理这个按键就返回。

#058 if (i8042KbdCallIsrHook(DeviceExtension, PortStatus, Output, &ToReturn))

#059 return ToReturn;

#060

处理键盘的数据是否需要重新输出到键盘。

#061 if (i8042PacketIsr(PortDeviceExtension, Output))

#062 {

#063 if (PortDeviceExtension->PacketComplete)

#064 {

#065 TRACE_(I8042PRT, "Packet complete/n");

#066 KeInsertQueueDpc(&DeviceExtension->DpcKeyboard, NULL, NULL);

#067 }

#068 TRACE_(I8042PRT, "Irq eaten by packet/n");

#069 return TRUE;

#070 }

#071

#072 TRACE_(I8042PRT, "Irq is keyboard input/n");

#073

到这里,已经说明是键盘输入数据。

#074 if (DeviceExtension->KeyboardScanState == Normal)

#075 {

判断扫描码是E0,还是E1

#076 switch (Output)

#077 {

#078 case 0xe0:

#079 DeviceExtension->KeyboardScanState = GotE0;

#080 return TRUE;

#081 case 0xe1:

#082 DeviceExtension->KeyboardScanState = GotE1;

#083 return TRUE;

#084 default:

#085 break;

#086 }

#087 }

#088

更新输入的数据。

#089 /* Update InputData */

#090 InputData->Flags = 0;

置位是E0,还是E1

#091 switch (DeviceExtension->KeyboardScanState)

#092 {

#093 case GotE0:

#094 InputData->Flags |= KEY_E0;

#095 break;

#096 case GotE1:

#097 InputData->Flags |= KEY_E1;

#098 break;

#099 default:

#100 break;

#101 }

设置按键是按下码,还是弹起码。

当键盘上有键被按下,松开,按住,键盘将产生扫描码( Scan Code ),这些扫描码将被 i8048 直接得到。扫描码有两种,Make Code Break Code。当一个键被按下或按住时产生的是 Make Code ,当一个键被松开产生的是 Break Code。每个键被分配了唯一的 Make Code Break Code ,这样主机通过扫描码就可以知道是哪一个键。简单的说就是按下键,产生一个 Make Code。松开键,产生一个 Break Code

#102 DeviceExtension->KeyboardScanState = Normal;

#103 if (Output & 0x80)

#104 InputData->Flags |= KEY_BREAK;

#105 else

#106 InputData->Flags |= KEY_MAKE;

只需要保存低7F值。

#107 InputData->MakeCode = Output & 0x7f;

#108 InputData->Reserved = 0;

#109

调用键盘队列返回包。其实这个函数是把数据放到环形缓冲区里,然后插入一个事件到DPC队列里,再由DPC队列来完成每个IRP包。

#110 DeviceExtension->KeyboardHook.QueueKeyboardPacket(DeviceExtension->KeyboardHook.CallContext);

#111

#112 return TRUE;

#113 }

#114

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值