您的位置:首页 > Web前端 > React

reactos操作系统实现(94)

2009-09-23 22:57 337 查看
现在就来依次分析函数i8042Create、i8042Cleanup、i8042Close、i8042DeviceControl、i8042InternalDeviceControl和i8042Pnp。首先分析函数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 }

缺省是调用函数ForwardIrpAndForget把IRP前面传送。

#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 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: