Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeni8042prt.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: drivers/input/i8042prt/i8042prt.c 00005 * PURPOSE: Driver entry function 00006 * PROGRAMMERS: Copyright Victor Kirhenshtein (sauros@iname.com) 00007 Copyright Jason Filby (jasonfilby@yahoo.com) 00008 Copyright Martijn Vernooij (o112w8r02@sneakemail.com) 00009 Copyright 2006-2007 Hervé Poussineau (hpoussin@reactos.org) 00010 */ 00011 00012 /* INCLUDES ******************************************************************/ 00013 00014 #define INITGUID 00015 #include "i8042prt.h" 00016 00017 /* FUNCTIONS *****************************************************************/ 00018 00019 static DRIVER_STARTIO i8042StartIo; 00020 static DRIVER_DISPATCH IrpStub; 00021 static DRIVER_DISPATCH i8042DeviceControl; 00022 static DRIVER_DISPATCH i8042InternalDeviceControl; 00023 DRIVER_INITIALIZE DriverEntry; 00024 00025 NTSTATUS NTAPI 00026 i8042AddDevice( 00027 IN PDRIVER_OBJECT DriverObject, 00028 IN PDEVICE_OBJECT Pdo) 00029 { 00030 PI8042_DRIVER_EXTENSION DriverExtension; 00031 PFDO_DEVICE_EXTENSION DeviceExtension = NULL; 00032 PDEVICE_OBJECT Fdo = NULL; 00033 ULONG DeviceExtensionSize; 00034 NTSTATUS Status; 00035 00036 TRACE_(I8042PRT, "i8042AddDevice(%p %p)\n", DriverObject, Pdo); 00037 00038 DriverExtension = (PI8042_DRIVER_EXTENSION)IoGetDriverObjectExtension(DriverObject, DriverObject); 00039 00040 if (Pdo == NULL) 00041 { 00042 /* We're getting a NULL Pdo at the first call as 00043 * we are a legacy driver. Ignore it */ 00044 return STATUS_SUCCESS; 00045 } 00046 00047 /* Create new device object. As we don't know if the device would be a keyboard 00048 * or a mouse, we have to allocate the biggest device extension. */ 00049 DeviceExtensionSize = MAX(sizeof(I8042_KEYBOARD_EXTENSION), sizeof(I8042_MOUSE_EXTENSION)); 00050 Status = IoCreateDevice( 00051 DriverObject, 00052 DeviceExtensionSize, 00053 NULL, 00054 Pdo->DeviceType, 00055 FILE_DEVICE_SECURE_OPEN, 00056 TRUE, 00057 &Fdo); 00058 if (!NT_SUCCESS(Status)) 00059 { 00060 WARN_(I8042PRT, "IoCreateDevice() failed with status 0x%08lx\n", Status); 00061 goto cleanup; 00062 } 00063 00064 DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension; 00065 RtlZeroMemory(DeviceExtension, DeviceExtensionSize); 00066 DeviceExtension->Type = Unknown; 00067 DeviceExtension->Fdo = Fdo; 00068 DeviceExtension->Pdo = Pdo; 00069 DeviceExtension->PortDeviceExtension = &DriverExtension->Port; 00070 Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice); 00071 if (!NT_SUCCESS(Status)) 00072 { 00073 WARN_(I8042PRT, "IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status); 00074 goto cleanup; 00075 } 00076 00077 ExInterlockedInsertTailList( 00078 &DriverExtension->DeviceListHead, 00079 &DeviceExtension->ListEntry, 00080 &DriverExtension->DeviceListLock); 00081 00082 Fdo->Flags &= ~DO_DEVICE_INITIALIZING; 00083 return STATUS_SUCCESS; 00084 00085 cleanup: 00086 if (DeviceExtension && DeviceExtension->LowerDevice) 00087 IoDetachDevice(DeviceExtension->LowerDevice); 00088 if (Fdo) 00089 IoDeleteDevice(Fdo); 00090 return Status; 00091 } 00092 00093 VOID NTAPI 00094 i8042SendHookWorkItem( 00095 IN PDEVICE_OBJECT DeviceObject, 00096 IN PVOID Context) 00097 { 00098 PI8042_HOOK_WORKITEM WorkItemData; 00099 PFDO_DEVICE_EXTENSION FdoDeviceExtension; 00100 PPORT_DEVICE_EXTENSION PortDeviceExtension; 00101 PDEVICE_OBJECT TopOfStack = NULL; 00102 ULONG IoControlCode; 00103 PVOID InputBuffer; 00104 ULONG InputBufferLength; 00105 IO_STATUS_BLOCK IoStatus; 00106 KEVENT Event; 00107 PIRP NewIrp; 00108 NTSTATUS Status; 00109 00110 TRACE_(I8042PRT, "i8042SendHookWorkItem(%p %p)\n", DeviceObject, Context); 00111 00112 WorkItemData = (PI8042_HOOK_WORKITEM)Context; 00113 FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00114 PortDeviceExtension = FdoDeviceExtension->PortDeviceExtension; 00115 00116 switch (FdoDeviceExtension->Type) 00117 { 00118 case Keyboard: 00119 { 00120 PI8042_KEYBOARD_EXTENSION DeviceExtension; 00121 DeviceExtension = (PI8042_KEYBOARD_EXTENSION)FdoDeviceExtension; 00122 IoControlCode = IOCTL_INTERNAL_I8042_HOOK_KEYBOARD; 00123 InputBuffer = &DeviceExtension->KeyboardHook; 00124 InputBufferLength = sizeof(INTERNAL_I8042_HOOK_KEYBOARD); 00125 break; 00126 } 00127 case Mouse: 00128 { 00129 PI8042_MOUSE_EXTENSION DeviceExtension; 00130 DeviceExtension = (PI8042_MOUSE_EXTENSION)FdoDeviceExtension; 00131 IoControlCode = IOCTL_INTERNAL_I8042_HOOK_MOUSE; 00132 InputBuffer = &DeviceExtension->MouseHook; 00133 InputBufferLength = sizeof(INTERNAL_I8042_HOOK_MOUSE); 00134 break; 00135 } 00136 default: 00137 { 00138 ERR_(I8042PRT, "Unknown FDO type %u\n", FdoDeviceExtension->Type); 00139 ASSERT(FALSE); 00140 WorkItemData->Irp->IoStatus.Status = STATUS_INTERNAL_ERROR; 00141 goto cleanup; 00142 } 00143 } 00144 00145 KeInitializeEvent(&Event, NotificationEvent, FALSE); 00146 TopOfStack = IoGetAttachedDeviceReference(DeviceObject); 00147 00148 NewIrp = IoBuildDeviceIoControlRequest( 00149 IoControlCode, 00150 TopOfStack, 00151 InputBuffer, 00152 InputBufferLength, 00153 NULL, 00154 0, 00155 TRUE, 00156 &Event, 00157 &IoStatus); 00158 00159 if (!NewIrp) 00160 { 00161 WARN_(I8042PRT, "IoBuildDeviceIoControlRequest() failed\n"); 00162 WorkItemData->Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 00163 goto cleanup; 00164 } 00165 00166 Status = IoCallDriver(TopOfStack, NewIrp); 00167 if (Status == STATUS_PENDING) 00168 { 00169 KeWaitForSingleObject( 00170 &Event, 00171 Executive, 00172 KernelMode, 00173 FALSE, 00174 NULL); 00175 Status = IoStatus.Status; 00176 } 00177 if (!NT_SUCCESS(Status)) 00178 { 00179 WARN_(I8042PRT, "IoCallDriver() failed with status 0x%08lx\n", Status); 00180 goto cleanup; 00181 } 00182 00183 if (FdoDeviceExtension->Type == Keyboard) 00184 { 00185 PI8042_KEYBOARD_EXTENSION DeviceExtension; 00186 00187 DeviceExtension = (PI8042_KEYBOARD_EXTENSION)FdoDeviceExtension; 00188 /* Call the hooked initialization if it exists */ 00189 if (DeviceExtension->KeyboardHook.InitializationRoutine) 00190 { 00191 Status = DeviceExtension->KeyboardHook.InitializationRoutine( 00192 DeviceExtension->KeyboardHook.Context, 00193 PortDeviceExtension, 00194 i8042SynchReadPort, 00195 i8042SynchWritePortKbd, 00196 FALSE); 00197 if (!NT_SUCCESS(Status)) 00198 { 00199 WARN_(I8042PRT, "KeyboardHook.InitializationRoutine() failed with status 0x%08lx\n", Status); 00200 WorkItemData->Irp->IoStatus.Status = Status; 00201 goto cleanup; 00202 } 00203 } 00204 } 00205 00206 WorkItemData->Irp->IoStatus.Status = STATUS_SUCCESS; 00207 00208 cleanup: 00209 if (TopOfStack != NULL) 00210 ObDereferenceObject(TopOfStack); 00211 WorkItemData->Irp->IoStatus.Information = 0; 00212 IoCompleteRequest(WorkItemData->Irp, IO_NO_INCREMENT); 00213 00214 IoFreeWorkItem(WorkItemData->WorkItem); 00215 ExFreePoolWithTag(WorkItemData, I8042PRT_TAG); 00216 } 00217 00218 static VOID NTAPI 00219 i8042StartIo( 00220 IN PDEVICE_OBJECT DeviceObject, 00221 IN PIRP Irp) 00222 { 00223 PFDO_DEVICE_EXTENSION DeviceExtension; 00224 00225 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00226 switch (DeviceExtension->Type) 00227 { 00228 case Keyboard: 00229 i8042KbdStartIo(DeviceObject, Irp); 00230 break; 00231 default: 00232 ERR_(I8042PRT, "Unknown FDO type %u\n", DeviceExtension->Type); 00233 ASSERT(FALSE); 00234 break; 00235 } 00236 } 00237 00238 /* Write the current byte of the packet. Returns FALSE in case 00239 * of problems. 00240 */ 00241 static BOOLEAN 00242 i8042PacketWrite( 00243 IN PPORT_DEVICE_EXTENSION DeviceExtension) 00244 { 00245 UCHAR Port = DeviceExtension->PacketPort; 00246 00247 if (Port) 00248 { 00249 if (!i8042Write(DeviceExtension, 00250 DeviceExtension->ControlPort, 00251 Port)) 00252 { 00253 /* something is really wrong! */ 00254 WARN_(I8042PRT, "Failed to send packet byte!\n"); 00255 return FALSE; 00256 } 00257 } 00258 00259 return i8042Write(DeviceExtension, 00260 DeviceExtension->DataPort, 00261 DeviceExtension->Packet.Bytes[DeviceExtension->Packet.CurrentByte]); 00262 } 00263 00264 BOOLEAN 00265 i8042PacketIsr( 00266 IN PPORT_DEVICE_EXTENSION DeviceExtension, 00267 IN UCHAR Output) 00268 { 00269 if (DeviceExtension->Packet.State == Idle) 00270 return FALSE; 00271 00272 switch (Output) 00273 { 00274 case KBD_RESEND: 00275 DeviceExtension->PacketResends++; 00276 if (DeviceExtension->PacketResends > DeviceExtension->Settings.ResendIterations) 00277 { 00278 DeviceExtension->Packet.State = Idle; 00279 DeviceExtension->PacketComplete = TRUE; 00280 DeviceExtension->PacketResult = STATUS_IO_TIMEOUT; 00281 DeviceExtension->PacketResends = 0; 00282 return TRUE; 00283 } 00284 DeviceExtension->Packet.CurrentByte--; 00285 break; 00286 00287 case KBD_NACK: 00288 DeviceExtension->Packet.State = Idle; 00289 DeviceExtension->PacketComplete = TRUE; 00290 DeviceExtension->PacketResult = STATUS_UNEXPECTED_IO_ERROR; 00291 DeviceExtension->PacketResends = 0; 00292 return TRUE; 00293 00294 default: 00295 DeviceExtension->PacketResends = 0; 00296 } 00297 00298 if (DeviceExtension->Packet.CurrentByte >= DeviceExtension->Packet.ByteCount) 00299 { 00300 DeviceExtension->Packet.State = Idle; 00301 DeviceExtension->PacketComplete = TRUE; 00302 DeviceExtension->PacketResult = STATUS_SUCCESS; 00303 return TRUE; 00304 } 00305 00306 if (!i8042PacketWrite(DeviceExtension)) 00307 { 00308 DeviceExtension->Packet.State = Idle; 00309 DeviceExtension->PacketComplete = TRUE; 00310 DeviceExtension->PacketResult = STATUS_IO_TIMEOUT; 00311 return TRUE; 00312 } 00313 DeviceExtension->Packet.CurrentByte++; 00314 00315 return TRUE; 00316 } 00317 00318 /* 00319 * This function starts a packet. It must be called with the 00320 * correct DIRQL. 00321 */ 00322 NTSTATUS 00323 i8042StartPacket( 00324 IN PPORT_DEVICE_EXTENSION DeviceExtension, 00325 IN PFDO_DEVICE_EXTENSION FdoDeviceExtension, 00326 IN PUCHAR Bytes, 00327 IN ULONG ByteCount, 00328 IN PIRP Irp) 00329 { 00330 KIRQL Irql; 00331 NTSTATUS Status; 00332 00333 Irql = KeAcquireInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt); 00334 00335 if (DeviceExtension->Packet.State != Idle) 00336 { 00337 Status = STATUS_DEVICE_BUSY; 00338 goto done; 00339 } 00340 00341 switch (FdoDeviceExtension->Type) 00342 { 00343 case Keyboard: DeviceExtension->PacketPort = 0; break; 00344 case Mouse: DeviceExtension->PacketPort = CTRL_WRITE_MOUSE; break; 00345 default: 00346 ERR_(I8042PRT, "Unknown FDO type %u\n", FdoDeviceExtension->Type); 00347 ASSERT(FALSE); 00348 Status = STATUS_INTERNAL_ERROR; 00349 goto done; 00350 } 00351 00352 DeviceExtension->Packet.Bytes = Bytes; 00353 DeviceExtension->Packet.CurrentByte = 0; 00354 DeviceExtension->Packet.ByteCount = ByteCount; 00355 DeviceExtension->Packet.State = SendingBytes; 00356 DeviceExtension->PacketResult = Status = STATUS_PENDING; 00357 DeviceExtension->CurrentIrp = Irp; 00358 DeviceExtension->CurrentIrpDevice = FdoDeviceExtension->Fdo; 00359 00360 if (!i8042PacketWrite(DeviceExtension)) 00361 { 00362 Status = STATUS_IO_TIMEOUT; 00363 DeviceExtension->Packet.State = Idle; 00364 DeviceExtension->PacketResult = STATUS_ABANDONED; 00365 goto done; 00366 } 00367 00368 DeviceExtension->Packet.CurrentByte++; 00369 00370 done: 00371 KeReleaseInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt, Irql); 00372 00373 if (Status != STATUS_PENDING) 00374 { 00375 DeviceExtension->CurrentIrp = NULL; 00376 DeviceExtension->CurrentIrpDevice = NULL; 00377 Irp->IoStatus.Status = Status; 00378 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00379 } 00380 return Status; 00381 } 00382 00383 static NTSTATUS NTAPI 00384 IrpStub( 00385 IN PDEVICE_OBJECT DeviceObject, 00386 IN PIRP Irp) 00387 { 00388 NTSTATUS Status = Irp->IoStatus.Status; 00389 00390 UNREFERENCED_PARAMETER(DeviceObject); 00391 00392 /* Do nothing */ 00393 ASSERT(FALSE); 00394 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00395 return Status; 00396 } 00397 00398 static NTSTATUS NTAPI 00399 i8042DeviceControl( 00400 IN PDEVICE_OBJECT DeviceObject, 00401 IN PIRP Irp) 00402 { 00403 PFDO_DEVICE_EXTENSION DeviceExtension; 00404 00405 TRACE_(I8042PRT, "i8042DeviceControl(%p %p)\n", DeviceObject, Irp); 00406 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00407 00408 switch (DeviceExtension->Type) 00409 { 00410 case Keyboard: 00411 return i8042KbdDeviceControl(DeviceObject, Irp); 00412 break; 00413 default: 00414 return IrpStub(DeviceObject, Irp); 00415 } 00416 } 00417 00418 static NTSTATUS NTAPI 00419 i8042InternalDeviceControl( 00420 IN PDEVICE_OBJECT DeviceObject, 00421 IN PIRP Irp) 00422 { 00423 PFDO_DEVICE_EXTENSION DeviceExtension; 00424 ULONG ControlCode; 00425 NTSTATUS Status; 00426 00427 TRACE_(I8042PRT, "i8042InternalDeviceControl(%p %p)\n", DeviceObject, Irp); 00428 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00429 00430 switch (DeviceExtension->Type) 00431 { 00432 case Unknown: 00433 { 00434 ControlCode = IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode; 00435 switch (ControlCode) 00436 { 00437 case IOCTL_INTERNAL_KEYBOARD_CONNECT: 00438 Status = i8042KbdInternalDeviceControl(DeviceObject, Irp); 00439 break; 00440 case IOCTL_INTERNAL_MOUSE_CONNECT: 00441 Status = i8042MouInternalDeviceControl(DeviceObject, Irp); 00442 break; 00443 default: 00444 ERR_(I8042PRT, "Unknown IO control code 0x%lx\n", ControlCode); 00445 ASSERT(FALSE); 00446 Status = STATUS_INVALID_DEVICE_REQUEST; 00447 break; 00448 } 00449 break; 00450 } 00451 case Keyboard: 00452 Status = i8042KbdInternalDeviceControl(DeviceObject, Irp); 00453 break; 00454 case Mouse: 00455 Status = i8042MouInternalDeviceControl(DeviceObject, Irp); 00456 break; 00457 default: 00458 ERR_(I8042PRT, "Unknown FDO type %u\n", DeviceExtension->Type); 00459 ASSERT(FALSE); 00460 Status = STATUS_INTERNAL_ERROR; 00461 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00462 break; 00463 } 00464 00465 return Status; 00466 } 00467 00468 NTSTATUS NTAPI 00469 DriverEntry( 00470 IN PDRIVER_OBJECT DriverObject, 00471 IN PUNICODE_STRING RegistryPath) 00472 { 00473 PI8042_DRIVER_EXTENSION DriverExtension; 00474 ULONG i; 00475 NTSTATUS Status; 00476 00477 /* ROS Hack: ideally, we shouldn't have to initialize debug level this way, 00478 but since the only way is to change it via KDBG, it's better to leave 00479 it here too. */ 00480 #if 0 00481 DbgSetDebugFilterState( 00482 DPFLTR_I8042PRT_ID, 00483 (1 << DPFLTR_ERROR_LEVEL) | (1 << DPFLTR_WARNING_LEVEL) | 00484 (1 << DPFLTR_TRACE_LEVEL) /*| (1 << DPFLTR_INFO_LEVEL)*/ | DPFLTR_MASK, 00485 TRUE); 00486 #endif 00487 00488 Status = IoAllocateDriverObjectExtension( 00489 DriverObject, 00490 DriverObject, 00491 sizeof(I8042_DRIVER_EXTENSION), 00492 (PVOID*)&DriverExtension); 00493 if (!NT_SUCCESS(Status)) 00494 { 00495 WARN_(I8042PRT, "IoAllocateDriverObjectExtension() failed with status 0x%08lx\n", Status); 00496 return Status; 00497 } 00498 RtlZeroMemory(DriverExtension, sizeof(I8042_DRIVER_EXTENSION)); 00499 KeInitializeSpinLock(&DriverExtension->Port.SpinLock); 00500 InitializeListHead(&DriverExtension->DeviceListHead); 00501 KeInitializeSpinLock(&DriverExtension->DeviceListLock); 00502 00503 Status = DuplicateUnicodeString( 00504 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, 00505 RegistryPath, 00506 &DriverExtension->RegistryPath); 00507 if (!NT_SUCCESS(Status)) 00508 { 00509 WARN_(I8042PRT, "DuplicateUnicodeString() failed with status 0x%08lx\n", Status); 00510 return Status; 00511 } 00512 00513 Status = ReadRegistryEntries(RegistryPath, &DriverExtension->Port.Settings); 00514 if (!NT_SUCCESS(Status)) 00515 { 00516 WARN_(I8042PRT, "ReadRegistryEntries() failed with status 0x%08lx\n", Status); 00517 return Status; 00518 } 00519 00520 DriverObject->DriverExtension->AddDevice = i8042AddDevice; 00521 DriverObject->DriverStartIo = i8042StartIo; 00522 00523 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) 00524 DriverObject->MajorFunction[i] = IrpStub; 00525 00526 DriverObject->MajorFunction[IRP_MJ_CREATE] = i8042Create; 00527 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = i8042Cleanup; 00528 DriverObject->MajorFunction[IRP_MJ_CLOSE] = i8042Close; 00529 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = i8042DeviceControl; 00530 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = i8042InternalDeviceControl; 00531 DriverObject->MajorFunction[IRP_MJ_PNP] = i8042Pnp; 00532 00533 return STATUS_SUCCESS; 00534 } Generated on Sun May 27 2012 04:27:49 for ReactOS by
1.7.6.1
|