reactos操作系统实现(94)
发布日期:2021-07-01 04:59:04 浏览次数:3 分类:技术文章

本文共 6731 字,大约阅读时间需要 22 分钟。

现在就来依次分析函数i8042Createi8042Cleanupi8042Closei8042DeviceControli8042InternalDeviceControli8042Pnp。首先分析函数i8042Create,它的实现代码如下:

#001  NTSTATUS NTAPI

#002  i8042Create(

#003     IN PDEVICE_OBJECT DeviceObject,

#004     IN PIRP Irp)

#005  {

#006     TRACE_(I8042PRT, "IRP_MJ_CREATE/n");

#007 

 

设置IRP的状态为成功。

#008     Irp->IoStatus.Status = STATUS_SUCCESS;

 

返回状态信息为0

#009     Irp->IoStatus.Information = 0;

 

调用函数IoCompleteRequest来设置当前IRP完成。

#010     IoCompleteRequest(Irp, IO_NO_INCREMENT);

#011     return STATUS_SUCCESS;

#012  }

 

函数i8042Cleanup,它的实现代码如下:

#001  NTSTATUS NTAPI

#002  i8042Cleanup(

#003     IN PDEVICE_OBJECT DeviceObject,

#004     IN PIRP Irp)

#005  {

#006     TRACE_(I8042PRT, "IRP_MJ_CLEANUP/n");

#007 

 

设置IRP的状态为成功。

#008     Irp->IoStatus.Status = STATUS_SUCCESS;

#009     Irp->IoStatus.Information = 0;

 

调用函数IoCompleteRequest来设置当前IRP完成。

#010     IoCompleteRequest(Irp, IO_NO_INCREMENT);

#011     return STATUS_SUCCESS;

#012  }

 

函数i8042Close,它的实现代码如下:

#001  NTSTATUS NTAPI

#002  i8042Close(

#003     IN PDEVICE_OBJECT DeviceObject,

#004     IN PIRP Irp)

#005  {

#006     TRACE_(I8042PRT, "IRP_MJ_CLOSE/n");

#007 

 

设置IRP的状态为成功。

#008     Irp->IoStatus.Status = STATUS_SUCCESS;

#009     Irp->IoStatus.Information = 0;

 

调用函数IoCompleteRequest来设置当前IRP完成。

#010     IoCompleteRequest(Irp, IO_NO_INCREMENT);

#011     return STATUS_SUCCESS;

#012  }

 

函数i8042DeviceControl,它的实现代码如下:

#001  static NTSTATUS NTAPI

#002  i8042DeviceControl(

#003     IN PDEVICE_OBJECT DeviceObject,

#004     IN PIRP Irp)

#005  {

#006     PFDO_DEVICE_EXTENSION DeviceExtension;

#007     NTSTATUS Status;

#008 

#009     TRACE_(I8042PRT, "i8042DeviceControl(%p %p)/n", DeviceObject, Irp);

 

获取设备扩展。

#010     DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

#011 

 

根设备类型来处理。

#012     switch (DeviceExtension->Type)

#013     {

 

这里处理键盘类型设备。

#014         case Keyboard:

#015             return i8042KbdDeviceControl(DeviceObject, Irp);

#016             break;

#017         default:

#018             return IrpStub(DeviceObject, Irp);

#019     }

#020 

#021     return Status;

#022  }

 

接着分析函数i8042KbdDeviceControl,它的实现代码如下:

#001  NTSTATUS NTAPI

#002  i8042KbdDeviceControl(

#003     IN PDEVICE_OBJECT DeviceObject,

#004     IN PIRP Irp)

#005  {

#006     PIO_STACK_LOCATION Stack;

#007     PI8042_KEYBOARD_EXTENSION DeviceExtension;

#008     NTSTATUS Status;

#009 

 

获取当前IRP的栈指针。

#010     Stack = IoGetCurrentIrpStackLocation(Irp);

 

设置返回状态信息为0个。

#011     Irp->IoStatus.Information = 0;

 

获取扩展设备。

#012     DeviceExtension = (PI8042_KEYBOARD_EXTENSION)DeviceObject->DeviceExtension;

#013 

 

根据IRP栈里的参数来获取操作码,然后根据操作码作不同的处理。

#014     switch (Stack->Parameters.DeviceIoControl.IoControlCode)

#015     {

 

获取系统的大写键状态。

#016         case IOCTL_GET_SYS_BUTTON_CAPS:

#017         {

#018             /* Part of GUID_DEVICE_SYS_BUTTON interface */

#019             PULONG pCaps;

#020             TRACE_(I8042PRT, "IOCTL_GET_SYS_BUTTON_CAPS/n");

#021 

 

如果返回参数内存空间不够4个字节长,就返回非法参数。

#022             if (Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(ULONG))

#023                 Status = STATUS_INVALID_PARAMETER;

#024             else

#025             {

 

获取系统保存参数位置。

#026                 pCaps = (PULONG)Irp->AssociatedIrp.SystemBuffer;

 

把键盘的大写状态返回给系统。

#027                 *pCaps = DeviceExtension->NewCaps;

#028                 DeviceExtension->ReportedCaps = DeviceExtension->NewCaps;

 

设置IRP返回参数的长度为4个字节。

#029                 Irp->IoStatus.Information = sizeof(ULONG);

 

设置返回状态为成功。

#030                 Status = STATUS_SUCCESS;

#031             }

#032             break;

#033         }

 

获取系统按键事件。

#034         case IOCTL_GET_SYS_BUTTON_EVENT:

#035         {

#036             /* Part of GUID_DEVICE_SYS_BUTTON interface */

#037             PIRP WaitingIrp;

#038             TRACE_(I8042PRT, "IOCTL_GET_SYS_BUTTON_EVENT/n");

#039 

 

判断是否可以返回参数,如果不可以返回,就直接返回出错。

#040             if (Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(ULONG))

#041                 Status = STATUS_INVALID_PARAMETER;

#042             else

#043             {

 

获取电源按键的事件。

#044                 WaitingIrp = InterlockedCompareExchangePointer(

#045                     &DeviceExtension->PowerIrp,

#046                     Irp,

#047                     NULL);

 

已经有一个事件的IRP在等待中,如果有就直接返回出错。

#048                 /* Check if an Irp is already pending */

#049                 if (WaitingIrp)

#050                 {

#051                     /* Unable to have a 2nd pending IRP for this IOCTL */

#052                     WARN_(I8042PRT, "Unable to pend a second IRP for IOCTL_GET_SYS_BUTTON_EVENT/n");

#053                     Status = STATUS_INVALID_PARAMETER;

#054                     Irp->IoStatus.Status = Status;

#055                     IoCompleteRequest(Irp, IO_NO_INCREMENT);

#056                 }

#057                 else

#058                 {

 

如果电源的IRP已经准备好,就直接返回给系统。

#059                     ULONG PowerKey;

#060                     PowerKey = InterlockedExchange((PLONG)&DeviceExtension->LastPowerKey, 0);

#061                     if (PowerKey != 0)

#062                     {

#063                         (VOID)InterlockedCompareExchangePointer(&DeviceExtension->PowerIrp, NULL, Irp);

#064                         *(PULONG)Irp->AssociatedIrp.SystemBuffer = PowerKey;

#065                         Status = STATUS_SUCCESS;

#066                         Irp->IoStatus.Status = Status;

#067                         Irp->IoStatus.Information = sizeof(ULONG);

#068                         IoCompleteRequest(Irp, IO_NO_INCREMENT);

#069                     }

#070                     else

#071                     {

#072                         TRACE_(I8042PRT, "Pending IOCTL_GET_SYS_BUTTON_EVENT/n");

#073                         Status = STATUS_PENDING;

#074                         Irp->IoStatus.Status = Status;

#075                         IoMarkIrpPending(Irp);

#076                     }

#077                 }

#078                 return Status;

#079             }

#080             break;

#081         }

 

缺省是调用函数ForwardIrpAndForgetIRP前面传送。

#082         default:

#083         {

#084             ERR_(I8042PRT, "IRP_MJ_DEVICE_CONTROL / unknown ioctl code 0x%lx/n",

#085                 Stack->Parameters.DeviceIoControl.IoControlCode);

#086             ASSERT(FALSE);

#087             return ForwardIrpAndForget(DeviceObject, Irp);

#088         }

#089     }

#090 

#091     Irp->IoStatus.Status = Status;

#092     if (Status == STATUS_PENDING)

 

这里调用函数IoMarkIrpPending来标记IRP正在阻塞中。

#093         IoMarkIrpPending(Irp);

#094     else

#095         IoCompleteRequest(Irp, IO_NO_INCREMENT);

#096 

#097     return Status;

#098  }

 

下面来分析函数i8042InternalDeviceControl的实现,代码如下:

#001  static NTSTATUS NTAPI

#002  i8042InternalDeviceControl(

#003     IN PDEVICE_OBJECT DeviceObject,

#004     IN PIRP Irp)

#005  {

#006     PFDO_DEVICE_EXTENSION DeviceExtension;

#007     ULONG ControlCode;

#008     NTSTATUS Status;

#009 

#010     TRACE_(I8042PRT, "i8042InternalDeviceControl(%p %p)/n", DeviceObject, Irp);

 

获取设备扩展。

#011     DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

#012 

 

根据设备扩展类型处理。

#013     switch (DeviceExtension->Type)

#014     {

 

不知道的类型处理。

#015         case Unknown:

#016         {

 

获取控制码。

#017             ControlCode = IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode;

 

根据控制码来处理。

#018             switch (ControlCode)

#019             {

 

内部键盘连接处理。

#020                 case IOCTL_INTERNAL_KEYBOARD_CONNECT:

 

进行内部的IRP处理。

#021                     Status = i8042KbdInternalDeviceControl(DeviceObject, Irp);

#022                     break;

 

内部鼠标连接处理。

#023                 case IOCTL_INTERNAL_MOUSE_CONNECT:

#024                     Status = i8042MouInternalDeviceControl(DeviceObject, Irp);

#025                     break;

#026                 default:

#027                     ERR_(I8042PRT, "Unknown IO control code 0x%lx/n", ControlCode);

#028                     ASSERT(FALSE);

#029                     Status = STATUS_INVALID_DEVICE_REQUEST;

#030                     break;

#031             }

#032             break;

#033         }

 

键盘处理内部IRP

#034         case Keyboard:

#035             Status = i8042KbdInternalDeviceControl(DeviceObject, Irp);

#036             break;

 

鼠标处理内部IRP

#037         case Mouse:

#038             Status = i8042MouInternalDeviceControl(DeviceObject, Irp);

#039             break;

#040         default:

#041             ERR_(I8042PRT, "Unknown FDO type %u/n", DeviceExtension->Type);

#042             ASSERT(FALSE);

#043             Status = STATUS_INTERNAL_ERROR;

#044             IoCompleteRequest(Irp, IO_NO_INCREMENT);

#045             break;

#046     }

#047 

#048     return Status;

#049  }

转载地址:https://mysoft.blog.csdn.net/article/details/4586244 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:reactos操作系统实现(95)
下一篇:使用Python快速实现显示器关闭和锁住桌面

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2024年04月15日 14时16分37秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章