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  

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

caimouse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值