Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencmbpnp.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS ACPI-Compliant Control Method Battery 00003 * LICENSE: BSD - See COPYING.ARM in the top level directory 00004 * FILE: boot/drivers/bus/acpi/cmbatt/cmbpnp.c 00005 * PURPOSE: Plug-and-Play IOCTL/IRP Handling 00006 * PROGRAMMERS: ReactOS Portable Systems Group 00007 */ 00008 00009 /* INCLUDES *******************************************************************/ 00010 00011 #include "cmbatt.h" 00012 00013 /* FUNCTIONS ******************************************************************/ 00014 00015 VOID 00016 NTAPI 00017 CmBattWaitWakeLoop(IN PDEVICE_OBJECT DeviceObject, 00018 IN UCHAR MinorFunction, 00019 IN POWER_STATE PowerState, 00020 IN PVOID Context, 00021 IN PIO_STATUS_BLOCK IoStatusBlock) 00022 { 00023 NTSTATUS Status; 00024 PCMBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; 00025 if (CmBattDebug & 0x20) DbgPrint("CmBattWaitWakeLoop: Entered.\n"); 00026 00027 /* Check for success */ 00028 if ((NT_SUCCESS(IoStatusBlock->Status)) && (DeviceExtension->WaitWakeEnable)) 00029 { 00030 /* Request a new power IRP */ 00031 if (CmBattDebug & 2) DbgPrint("CmBattWaitWakeLoop: completed successfully\n"); 00032 Status = PoRequestPowerIrp(DeviceObject, 00033 MinorFunction, 00034 PowerState, 00035 CmBattWaitWakeLoop, 00036 Context, 00037 &DeviceExtension->PowerIrp); 00038 if (CmBattDebug & 2) 00039 DbgPrint("CmBattWaitWakeLoop: PoRequestPowerIrp: status = 0x%08x.\n", 00040 Status); 00041 } 00042 else 00043 { 00044 /* Clear the power IRP, we failed */ 00045 if (CmBattDebug & 0xC) 00046 DbgPrint("CmBattWaitWakeLoop: failed: status = 0x%08x.\n", 00047 IoStatusBlock->Status); 00048 DeviceExtension->PowerIrp = NULL; 00049 } 00050 } 00051 00052 NTSTATUS 00053 NTAPI 00054 CmBattIoCompletion(IN PDEVICE_OBJECT DeviceObject, 00055 IN PIRP Irp, 00056 IN PKEVENT Event) 00057 { 00058 if (CmBattDebug & 2) DbgPrint("CmBattIoCompletion: Event (%x)\n", Event); 00059 00060 /* Set the completion event */ 00061 KeSetEvent(Event, IO_NO_INCREMENT, FALSE); 00062 return STATUS_MORE_PROCESSING_REQUIRED; 00063 } 00064 00065 NTSTATUS 00066 NTAPI 00067 CmBattGetAcpiInterfaces(IN PDEVICE_OBJECT DeviceObject, 00068 IN OUT PACPI_INTERFACE_STANDARD AcpiInterface) 00069 { 00070 PIRP Irp; 00071 NTSTATUS Status; 00072 PIO_STACK_LOCATION IoStackLocation; 00073 KEVENT Event; 00074 00075 /* Allocate the IRP */ 00076 Irp = IoAllocateIrp(DeviceObject->StackSize, 0); 00077 if (!Irp) 00078 { 00079 /* Fail */ 00080 if (CmBattDebug & 0xC) 00081 DbgPrint("CmBattGetAcpiInterfaces: Failed to allocate Irp\n"); 00082 return STATUS_INSUFFICIENT_RESOURCES; 00083 } 00084 00085 /* Set default error code */ 00086 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 00087 00088 /* Build the query */ 00089 IoStackLocation = IoGetNextIrpStackLocation(Irp); 00090 IoStackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE; 00091 IoStackLocation->Parameters.QueryInterface.InterfaceType = &GUID_ACPI_INTERFACE_STANDARD; 00092 IoStackLocation->Parameters.QueryInterface.Size = sizeof(ACPI_INTERFACE_STANDARD); 00093 IoStackLocation->Parameters.QueryInterface.Version = 1; 00094 IoStackLocation->Parameters.QueryInterface.Interface = (PINTERFACE)AcpiInterface; 00095 IoStackLocation->Parameters.QueryInterface.InterfaceSpecificData = NULL; 00096 00097 /* Set default ACPI interface data */ 00098 AcpiInterface->Size = sizeof(ACPI_INTERFACE_STANDARD); 00099 AcpiInterface->Version = 1; 00100 00101 /* Initialize our wait event */ 00102 KeInitializeEvent(&Event, SynchronizationEvent, 0); 00103 00104 /* Set the completion routine */ 00105 IoCopyCurrentIrpStackLocationToNext(Irp); 00106 IoSetCompletionRoutine(Irp, 00107 (PVOID)CmBattIoCompletion, 00108 &Event, 00109 TRUE, 00110 TRUE, 00111 TRUE); 00112 00113 /* Now call ACPI */ 00114 Status = IoCallDriver(DeviceObject, Irp); 00115 if (Status == STATUS_PENDING) 00116 { 00117 /* Wait for completion */ 00118 KeWaitForSingleObject(&Event, 00119 Executive, 00120 KernelMode, 00121 FALSE, 00122 NULL); 00123 Status = Irp->IoStatus.Status; 00124 } 00125 00126 /* Free the IRP */ 00127 IoFreeIrp(Irp); 00128 00129 /* Return status */ 00130 if (!(NT_SUCCESS(Status)) && (CmBattDebug & 0xC)) 00131 DbgPrint("CmBattGetAcpiInterfaces: Could not get ACPI driver interfaces, status = %x\n", Status); 00132 return Status; 00133 } 00134 00135 VOID 00136 NTAPI 00137 CmBattDestroyFdo(IN PDEVICE_OBJECT DeviceObject) 00138 { 00139 PAGED_CODE(); 00140 if (CmBattDebug & 0x220) DbgPrint("CmBattDestroyFdo, Battery.\n"); 00141 00142 /* Delete the device */ 00143 IoDeleteDevice(DeviceObject); 00144 if (CmBattDebug & 0x220) DbgPrint("CmBattDestroyFdo: done.\n"); 00145 } 00146 00147 NTSTATUS 00148 NTAPI 00149 CmBattRemoveDevice(IN PDEVICE_OBJECT DeviceObject, 00150 IN PIRP Irp) 00151 { 00152 PCMBATT_DEVICE_EXTENSION DeviceExtension; 00153 PVOID Context; 00154 DeviceExtension = DeviceObject->DeviceExtension; 00155 if (CmBattDebug & 2) 00156 DbgPrint("CmBattRemoveDevice: CmBatt (%x), Type %d, _UID %d\n", 00157 DeviceExtension, 00158 DeviceExtension->FdoType, 00159 DeviceExtension->DeviceId); 00160 00161 /* Make sure it's safe to go ahead */ 00162 IoReleaseRemoveLockAndWait(&DeviceExtension->RemoveLock, 0); 00163 00164 /* Check for pending power IRP */ 00165 if (DeviceExtension->PowerIrp) 00166 { 00167 /* Cancel and clear */ 00168 IoCancelIrp(DeviceExtension->PowerIrp); 00169 DeviceExtension->PowerIrp = NULL; 00170 } 00171 00172 /* Check what type of FDO is being removed */ 00173 Context = DeviceExtension->AcpiInterface.Context; 00174 if (DeviceExtension->FdoType == CmBattBattery) 00175 { 00176 /* Unregister battery FDO */ 00177 DeviceExtension->AcpiInterface.UnregisterForDeviceNotifications(Context, 00178 (PVOID)CmBattNotifyHandler); 00179 CmBattWmiDeRegistration(DeviceExtension); 00180 if (!NT_SUCCESS(BatteryClassUnload(DeviceExtension->ClassData))) ASSERT(FALSE); 00181 } 00182 else 00183 { 00184 /* Unregister AC adapter FDO */ 00185 DeviceExtension->AcpiInterface.UnregisterForDeviceNotifications(Context, 00186 (PVOID)CmBattNotifyHandler); 00187 CmBattWmiDeRegistration(DeviceExtension); 00188 AcAdapterPdo = NULL; 00189 } 00190 00191 /* Detach and delete */ 00192 IoDetachDevice(DeviceExtension->AttachedDevice); 00193 IoDeleteDevice(DeviceExtension->DeviceObject); 00194 return STATUS_SUCCESS; 00195 } 00196 00197 NTSTATUS 00198 NTAPI 00199 CmBattPowerDispatch(IN PDEVICE_OBJECT DeviceObject, 00200 IN PIRP Irp) 00201 { 00202 PIO_STACK_LOCATION IoStackLocation; 00203 PCMBATT_DEVICE_EXTENSION DeviceExtension; 00204 NTSTATUS Status; 00205 if (CmBattDebug & 0x210) DbgPrint("CmBattPowerDispatch\n"); 00206 00207 /* Get stack location and device extension */ 00208 IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 00209 DeviceExtension = DeviceObject->DeviceExtension; 00210 switch (IoStackLocation->MinorFunction) 00211 { 00212 case IRP_MN_WAIT_WAKE: 00213 if (CmBattDebug & 0x10) 00214 DbgPrint("CmBattPowerDispatch: IRP_MN_WAIT_WAKE\n"); 00215 break; 00216 00217 case IRP_MN_POWER_SEQUENCE: 00218 if (CmBattDebug & 0x10) 00219 DbgPrint("CmBattPowerDispatch: IRP_MN_POWER_SEQUENCE\n"); 00220 break; 00221 00222 case IRP_MN_QUERY_POWER: 00223 if (CmBattDebug & 0x10) 00224 DbgPrint("CmBattPowerDispatch: IRP_MN_WAIT_WAKE\n"); 00225 break; 00226 00227 case IRP_MN_SET_POWER: 00228 if (CmBattDebug & 0x10) 00229 DbgPrint("CmBattPowerDispatch: IRP_MN_SET_POWER type: %d, State: %d \n", 00230 IoStackLocation->Parameters.Power.Type, 00231 IoStackLocation->Parameters.Power.State); 00232 break; 00233 00234 default: 00235 00236 if (CmBattDebug & 1) 00237 DbgPrint("CmBattPowerDispatch: minor %d\n", IoStackLocation->MinorFunction); 00238 break; 00239 } 00240 00241 /* Start the next IRP and see if we're attached */ 00242 PoStartNextPowerIrp(Irp); 00243 if (DeviceExtension->AttachedDevice) 00244 { 00245 /* Call ACPI */ 00246 IoSkipCurrentIrpStackLocation(Irp); 00247 Status = PoCallDriver(DeviceExtension->AttachedDevice, Irp); 00248 } 00249 else 00250 { 00251 /* Complete the request here */ 00252 Status = Irp->IoStatus.Status; 00253 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00254 } 00255 00256 /* Return status */ 00257 return Status; 00258 } 00259 00260 NTSTATUS 00261 NTAPI 00262 CmBattPnpDispatch(IN PDEVICE_OBJECT DeviceObject, 00263 IN PIRP Irp) 00264 { 00265 PIO_STACK_LOCATION IoStackLocation; 00266 PCMBATT_DEVICE_EXTENSION DeviceExtension; 00267 NTSTATUS Status; 00268 KEVENT Event; 00269 PAGED_CODE(); 00270 00271 /* Get stack location and device extension */ 00272 IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 00273 DeviceExtension = DeviceObject->DeviceExtension; 00274 00275 /* Set default error */ 00276 Status = STATUS_NOT_SUPPORTED; 00277 00278 /* Try to acquire the lock before doing anything */ 00279 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, 0); 00280 if (!NT_SUCCESS(Status)) 00281 { 00282 /* Complete the request */ 00283 Irp->IoStatus.Status = STATUS_DEVICE_REMOVED; 00284 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00285 return STATUS_DEVICE_REMOVED; 00286 } 00287 00288 /* What's the operation? */ 00289 switch (IoStackLocation->MinorFunction) 00290 { 00291 case IRP_MN_QUERY_PNP_DEVICE_STATE: 00292 00293 /* Initialize our wait event */ 00294 KeInitializeEvent(&Event, SynchronizationEvent, 0); 00295 00296 /* Set the completion routine */ 00297 IoCopyCurrentIrpStackLocationToNext(Irp); 00298 IoSetCompletionRoutine(Irp, 00299 (PVOID)CmBattIoCompletion, 00300 &Event, 00301 TRUE, 00302 TRUE, 00303 TRUE); 00304 00305 /* Now call ACPI to inherit its PnP Device State */ 00306 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp); 00307 if (Status == STATUS_PENDING) 00308 { 00309 /* Wait for completion */ 00310 KeWaitForSingleObject(&Event, 00311 Executive, 00312 KernelMode, 00313 FALSE, 00314 NULL); 00315 Status = Irp->IoStatus.Status; 00316 } 00317 00318 /* However, a battery CAN be disabled */ 00319 Irp->IoStatus.Information &= ~PNP_DEVICE_NOT_DISABLEABLE; 00320 00321 /* Release the remove lock and complete the request */ 00322 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00323 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp); 00324 return Status; 00325 00326 case IRP_MN_SURPRISE_REMOVAL: 00327 if (CmBattDebug & 0x20) 00328 DbgPrint("CmBattPnpDispatch: IRP_MN_SURPRISE_REMOVAL\n"); 00329 00330 /* Lock the device extension and set the handle count to invalid */ 00331 ExAcquireFastMutex(&DeviceExtension->FastMutex); 00332 DeviceExtension->HandleCount = -1; 00333 ExReleaseFastMutex(&DeviceExtension->FastMutex); 00334 Status = STATUS_SUCCESS; 00335 break; 00336 00337 case IRP_MN_START_DEVICE: 00338 if (CmBattDebug & 0x20) 00339 DbgPrint("CmBattPnpDispatch: IRP_MN_START_DEVICE\n"); 00340 00341 /* Mark the extension as started */ 00342 if (DeviceExtension->FdoType == CmBattBattery) DeviceExtension->Started = TRUE; 00343 Status = STATUS_SUCCESS; 00344 break; 00345 00346 case IRP_MN_STOP_DEVICE: 00347 if (CmBattDebug & 0x20) 00348 DbgPrint("CmBattPnpDispatch: IRP_MN_STOP_DEVICE\n"); 00349 00350 /* Mark the extension as stopped */ 00351 if (DeviceExtension->FdoType == CmBattBattery) DeviceExtension->Started = FALSE; 00352 Status = STATUS_SUCCESS; 00353 break; 00354 00355 case IRP_MN_QUERY_REMOVE_DEVICE: 00356 if (CmBattDebug & 0x20) 00357 DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_REMOVE_DEVICE\n"); 00358 00359 /* Lock the extension and get the current handle count */ 00360 ExAcquireFastMutex(&DeviceExtension->FastMutex); 00361 if (DeviceExtension->HandleCount == 0) 00362 { 00363 /* No handles. Mark it as invalid since it'll be removed */ 00364 DeviceExtension->HandleCount = -1; 00365 Status = STATUS_SUCCESS; 00366 } 00367 else if (DeviceExtension->HandleCount == -1) 00368 { 00369 /* Don't do anything, but this is strange since it's already removed */ 00370 Status = STATUS_SUCCESS; 00371 if (CmBattDebug & 4) 00372 DbgPrint("CmBattPnpDispatch: Recieved two consecutive QUERY_REMOVE requests.\n"); 00373 } 00374 else 00375 { 00376 /* Fail because there's still open handles */ 00377 Status = STATUS_UNSUCCESSFUL; 00378 } 00379 00380 /* Release the lock and return */ 00381 ExReleaseFastMutex(&DeviceExtension->FastMutex); 00382 break; 00383 00384 case IRP_MN_REMOVE_DEVICE: 00385 if (CmBattDebug & 0x20) 00386 DbgPrint("CmBattPnpDispatch: IRP_MN_REMOVE_DEVICE\n"); 00387 00388 /* Call the remove code */ 00389 Status = CmBattRemoveDevice(DeviceObject, Irp); 00390 break; 00391 00392 case IRP_MN_CANCEL_REMOVE_DEVICE: 00393 if (CmBattDebug & 0x20) 00394 DbgPrint("CmBattPnpDispatch: IRP_MN_CANCEL_REMOVE_DEVICE\n"); 00395 00396 /* Lock the extension and get the handle count */ 00397 ExAcquireFastMutex(&DeviceExtension->FastMutex); 00398 if (DeviceExtension->HandleCount == -1) 00399 { 00400 /* A remove was in progress, set the handle count back to 0 */ 00401 DeviceExtension->HandleCount = 0; 00402 } 00403 else if (CmBattDebug & 2) 00404 { 00405 /* Nop, but warn about it */ 00406 DbgPrint("CmBattPnpDispatch: Received CANCEL_REMOVE when OpenCount == %x\n", 00407 DeviceExtension->HandleCount); 00408 } 00409 00410 /* Return success in all cases, and release the lock */ 00411 Status = STATUS_SUCCESS; 00412 ExReleaseFastMutex(&DeviceExtension->FastMutex); 00413 break; 00414 00415 case IRP_MN_QUERY_STOP_DEVICE: 00416 if (CmBattDebug & 0x20) 00417 DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_STOP_DEVICE\n"); 00418 00419 /* There's no real support for this */ 00420 Status = STATUS_NOT_IMPLEMENTED; 00421 break; 00422 00423 case IRP_MN_CANCEL_STOP_DEVICE: 00424 if (CmBattDebug & 0x20) 00425 DbgPrint("CmBattPnpDispatch: IRP_MN_CANCEL_STOP_DEVICE\n"); 00426 00427 /* There's no real support for this */ 00428 Status = STATUS_NOT_IMPLEMENTED; 00429 break; 00430 00431 case IRP_MN_QUERY_CAPABILITIES: 00432 00433 /* Initialize our wait event */ 00434 KeInitializeEvent(&Event, SynchronizationEvent, 0); 00435 00436 /* Set the completion routine */ 00437 IoCopyCurrentIrpStackLocationToNext(Irp); 00438 IoSetCompletionRoutine(Irp, 00439 (PVOID)CmBattIoCompletion, 00440 &Event, 00441 TRUE, 00442 TRUE, 00443 TRUE); 00444 00445 /* Now call ACPI */ 00446 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp); 00447 if (Status == STATUS_PENDING) 00448 { 00449 /* Wait for completion */ 00450 KeWaitForSingleObject(&Event, 00451 Executive, 00452 KernelMode, 00453 FALSE, 00454 NULL); 00455 Status = Irp->IoStatus.Status; 00456 } 00457 00458 /* Get the wake power state */ 00459 DeviceExtension->PowerState.SystemState = IoStackLocation->Parameters.DeviceCapabilities.Capabilities->SystemWake; 00460 if (CmBattDebug & 0x20) 00461 DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES %d Capabilities->SystemWake = %x\n", 00462 DeviceExtension->FdoType, 00463 DeviceExtension->PowerState); 00464 00465 /* Check if it's invalid */ 00466 if (DeviceExtension->PowerState.SystemState == PowerSystemUnspecified) 00467 { 00468 /* Wait wake is not supported in this scenario */ 00469 DeviceExtension->WaitWakeEnable = FALSE; 00470 if (CmBattDebug & 0x20) 00471 DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES Wake not supported.\n"); 00472 } 00473 else if (!(DeviceExtension->PowerIrp) && 00474 (DeviceExtension->WaitWakeEnable)) 00475 { 00476 /* If it was requested in the registry, request the power IRP for it */ 00477 PoRequestPowerIrp(DeviceExtension->DeviceObject, 00478 0, 00479 DeviceExtension->PowerState, 00480 CmBattWaitWakeLoop, 00481 0, 00482 &DeviceExtension->PowerIrp); 00483 if (CmBattDebug & 0x20) 00484 DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES wait/Wake irp sent.\n"); 00485 } 00486 00487 /* Release the remove lock and complete the request */ 00488 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00489 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp); 00490 return Status; 00491 00492 default: 00493 /* Unsupported */ 00494 if (CmBattDebug & 0x20) 00495 DbgPrint("CmBattPnpDispatch: Unimplemented minor %0x\n", 00496 IoStackLocation->MinorFunction); 00497 break; 00498 } 00499 00500 /* Release the remove lock */ 00501 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp); 00502 00503 /* Set IRP status if we have one */ 00504 if (Status != STATUS_NOT_SUPPORTED) Irp->IoStatus.Status = Status; 00505 00506 /* Did someone pick it up? */ 00507 if ((NT_SUCCESS(Status)) || (Status == STATUS_NOT_SUPPORTED)) 00508 { 00509 /* Still unsupported, try ACPI */ 00510 IoSkipCurrentIrpStackLocation(Irp); 00511 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp); 00512 } 00513 else 00514 { 00515 /* Complete the request */ 00516 Status = Irp->IoStatus.Status; 00517 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00518 } 00519 00520 /* Release the remove lock and return status */ 00521 return Status; 00522 } 00523 00524 NTSTATUS 00525 NTAPI 00526 CmBattCreateFdo(IN PDRIVER_OBJECT DriverObject, 00527 IN PDEVICE_OBJECT DeviceObject, 00528 IN ULONG DeviceExtensionSize, 00529 IN PDEVICE_OBJECT *NewDeviceObject) 00530 { 00531 PDEVICE_OBJECT FdoDeviceObject; 00532 HANDLE KeyHandle; 00533 PCMBATT_DEVICE_EXTENSION FdoExtension; 00534 UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)]; 00535 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PVOID)Buffer; 00536 NTSTATUS Status; 00537 UNICODE_STRING KeyString; 00538 ULONG UniqueId; 00539 ULONG ResultLength; 00540 PAGED_CODE(); 00541 if (CmBattDebug & 0x220) DbgPrint("CmBattCreateFdo: Entered\n"); 00542 00543 /* Get unique ID */ 00544 Status = CmBattGetUniqueId(DeviceObject, &UniqueId); 00545 if (!NT_SUCCESS(Status)) 00546 { 00547 /* Assume 0 */ 00548 UniqueId = 0; 00549 if (CmBattDebug & 2) 00550 DbgPrint("CmBattCreateFdo: Error %x from _UID, assuming unit #0\n", Status); 00551 } 00552 00553 /* Create the FDO */ 00554 Status = IoCreateDevice(DriverObject, 00555 DeviceExtensionSize, 00556 0, 00557 FILE_DEVICE_BATTERY, 00558 FILE_DEVICE_SECURE_OPEN, 00559 0, 00560 &FdoDeviceObject); 00561 if (!NT_SUCCESS(Status)) 00562 { 00563 /* Fail */ 00564 if (CmBattDebug & 0xC) 00565 DbgPrint("CmBattCreateFdo: error (0x%x) creating device object\n", Status); 00566 return Status; 00567 } 00568 00569 /* Set FDO flags */ 00570 FdoDeviceObject->Flags |= (DO_POWER_PAGABLE | DO_BUFFERED_IO); 00571 FdoDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 00572 00573 /* Initialize the extension */ 00574 FdoExtension = FdoDeviceObject->DeviceExtension; 00575 RtlZeroMemory(FdoExtension, DeviceExtensionSize); 00576 FdoExtension->DeviceObject = FdoDeviceObject; 00577 FdoExtension->FdoDeviceObject = FdoDeviceObject; 00578 FdoExtension->PdoDeviceObject = DeviceObject; 00579 00580 /* Attach to ACPI */ 00581 FdoExtension->AttachedDevice = IoAttachDeviceToDeviceStack(FdoDeviceObject, 00582 DeviceObject); 00583 if (!FdoExtension->AttachedDevice) 00584 { 00585 /* Destroy and fail */ 00586 CmBattDestroyFdo(FdoExtension->FdoDeviceObject); 00587 if (CmBattDebug & 0xC) 00588 DbgPrint("CmBattCreateFdo: IoAttachDeviceToDeviceStack failed.\n"); 00589 return STATUS_UNSUCCESSFUL; 00590 } 00591 00592 /* Get ACPI interface for EVAL */ 00593 Status = CmBattGetAcpiInterfaces(FdoExtension->AttachedDevice, 00594 &FdoExtension->AcpiInterface); 00595 if (!FdoExtension->AttachedDevice) 00596 { 00597 /* Detach, destroy, and fail */ 00598 IoDetachDevice(FdoExtension->AttachedDevice); 00599 CmBattDestroyFdo(FdoExtension->FdoDeviceObject); 00600 if (CmBattDebug & 0xC) 00601 DbgPrint("CmBattCreateFdo: Could not get ACPI interfaces: %x\n", Status); 00602 return STATUS_UNSUCCESSFUL; 00603 } 00604 00605 /* Setup the rest of the extension */ 00606 ExInitializeFastMutex(&FdoExtension->FastMutex); 00607 IoInitializeRemoveLock(&FdoExtension->RemoveLock, 0, 0, 0); 00608 FdoExtension->HandleCount = 0; 00609 FdoExtension->WaitWakeEnable = FALSE; 00610 FdoExtension->DeviceId = UniqueId; 00611 FdoExtension->DeviceName = NULL; 00612 FdoExtension->DelayNotification = FALSE; 00613 FdoExtension->ArFlag = 0; 00614 00615 /* Open the device key */ 00616 Status = IoOpenDeviceRegistryKey(DeviceObject, 00617 PLUGPLAY_REGKEY_DEVICE, 00618 KEY_READ, 00619 &KeyHandle); 00620 if (NT_SUCCESS(Status)) 00621 { 00622 /* Read wait wake value */ 00623 RtlInitUnicodeString(&KeyString, L"WaitWakeEnabled"); 00624 Status = ZwQueryValueKey(KeyHandle, 00625 &KeyString, 00626 KeyValuePartialInformation, 00627 PartialInfo, 00628 sizeof(Buffer), 00629 &ResultLength); 00630 if (NT_SUCCESS(Status)) 00631 { 00632 /* Set value */ 00633 FdoExtension->WaitWakeEnable = *(PULONG)PartialInfo->Data; 00634 } 00635 00636 /* Close the handle */ 00637 ZwClose(KeyHandle); 00638 } 00639 00640 /* Return success and the new FDO */ 00641 *NewDeviceObject = FdoDeviceObject; 00642 if (CmBattDebug & 0x220) 00643 DbgPrint("CmBattCreateFdo: Created FDO %x\n", FdoDeviceObject); 00644 return STATUS_SUCCESS; 00645 } 00646 00647 NTSTATUS 00648 NTAPI 00649 CmBattAddBattery(IN PDRIVER_OBJECT DriverObject, 00650 IN PDEVICE_OBJECT DeviceObject) 00651 { 00652 BATTERY_MINIPORT_INFO MiniportInfo; 00653 NTSTATUS Status; 00654 PDEVICE_OBJECT FdoDeviceObject; 00655 PCMBATT_DEVICE_EXTENSION FdoExtension; 00656 PAGED_CODE(); 00657 if (CmBattDebug & 0x220) 00658 DbgPrint("CmBattAddBattery: pdo %x\n", DeviceObject); 00659 00660 /* Create the FDO */ 00661 Status = CmBattCreateFdo(DriverObject, 00662 DeviceObject, 00663 sizeof(CMBATT_DEVICE_EXTENSION), 00664 &FdoDeviceObject); 00665 if (!NT_SUCCESS(Status)) 00666 { 00667 if (CmBattDebug & 0xC) 00668 DbgPrint("CmBattAddBattery: error (0x%x) creating Fdo\n", Status); 00669 return Status; 00670 } 00671 00672 /* Build the FDO extensio, check if we support trip points */ 00673 FdoExtension = FdoDeviceObject->DeviceExtension; 00674 FdoExtension->FdoType = CmBattBattery; 00675 FdoExtension->Started = 0; 00676 FdoExtension->NotifySent = TRUE; 00677 InterlockedExchange(&FdoExtension->ArLockValue, 0); 00678 FdoExtension->TripPointValue = BATTERY_UNKNOWN_CAPACITY; 00679 FdoExtension->Tag = 0; 00680 FdoExtension->InterruptTime = KeQueryInterruptTime(); 00681 FdoExtension->TripPointSet = CmBattSetTripPpoint(FdoExtension, 0) != 00682 STATUS_OBJECT_NAME_NOT_FOUND; 00683 00684 /* Setup the battery miniport information structure */ 00685 RtlZeroMemory(&MiniportInfo, sizeof(MiniportInfo)); 00686 MiniportInfo.Pdo = DeviceObject; 00687 MiniportInfo.MajorVersion = BATTERY_CLASS_MAJOR_VERSION; 00688 MiniportInfo.MinorVersion = BATTERY_CLASS_MINOR_VERSION; 00689 MiniportInfo.Context = FdoExtension; 00690 MiniportInfo.QueryTag = (PVOID)CmBattQueryTag; 00691 MiniportInfo.QueryInformation = (PVOID)CmBattQueryInformation; 00692 MiniportInfo.SetInformation = NULL; 00693 MiniportInfo.QueryStatus = (PVOID)CmBattQueryStatus; 00694 MiniportInfo.SetStatusNotify = (PVOID)CmBattSetStatusNotify; 00695 MiniportInfo.DisableStatusNotify = (PVOID)CmBattDisableStatusNotify; 00696 MiniportInfo.DeviceName = FdoExtension->DeviceName; 00697 00698 /* Register with the class driver */ 00699 Status = BatteryClassInitializeDevice(&MiniportInfo, &FdoExtension->ClassData); 00700 if (!NT_SUCCESS(Status)) 00701 { 00702 IoDetachDevice(FdoExtension->AttachedDevice); 00703 CmBattDestroyFdo(FdoExtension->FdoDeviceObject); 00704 if (CmBattDebug & 0xC) 00705 DbgPrint("CmBattAddBattery: error (0x%x) registering with class\n", Status); 00706 return Status; 00707 } 00708 00709 /* Register WMI */ 00710 Status = CmBattWmiRegistration(FdoExtension); 00711 if (!NT_SUCCESS(Status)) 00712 { 00713 if (CmBattDebug & 0xC) 00714 DbgPrint("CmBattAddBattery: Could not register as a WMI provider, status = %Lx\n", Status); 00715 return Status; 00716 } 00717 00718 /* Register ACPI */ 00719 Status = FdoExtension->AcpiInterface.RegisterForDeviceNotifications(FdoExtension->AcpiInterface.Context, 00720 (PVOID)CmBattNotifyHandler, 00721 FdoExtension); 00722 if (!NT_SUCCESS(Status)) 00723 { 00724 CmBattWmiDeRegistration(FdoExtension); 00725 BatteryClassUnload(FdoExtension->ClassData); 00726 IoDetachDevice(FdoExtension->AttachedDevice); 00727 CmBattDestroyFdo(FdoExtension->FdoDeviceObject); 00728 if (CmBattDebug & 0xC) 00729 DbgPrint("CmBattAddBattery: Could not register for battery notify, status = %Lx\n", Status); 00730 } 00731 00732 /* Return status */ 00733 return Status; 00734 } 00735 00736 NTSTATUS 00737 NTAPI 00738 CmBattAddAcAdapter(IN PDRIVER_OBJECT DriverObject, 00739 IN PDEVICE_OBJECT PdoDeviceObject) 00740 { 00741 PDEVICE_OBJECT FdoDeviceObject; 00742 NTSTATUS Status; 00743 PCMBATT_DEVICE_EXTENSION DeviceExtension; 00744 PAGED_CODE(); 00745 if (CmBattDebug & 0x220) 00746 DbgPrint("CmBattAddAcAdapter: pdo %x\n", PdoDeviceObject); 00747 00748 /* Check if we already have an AC adapter */ 00749 if (AcAdapterPdo) 00750 { 00751 /* Don't do anything */ 00752 if (CmBattDebug & 0xC) 00753 DbgPrint("CmBatt: Second AC adapter found. Current version of driver only supports 1 aadapter.\n"); 00754 } 00755 else 00756 { 00757 /* Set this as the AC adapter's PDO */ 00758 AcAdapterPdo = PdoDeviceObject; 00759 } 00760 00761 /* Create the FDO for the adapter */ 00762 Status = CmBattCreateFdo(DriverObject, 00763 PdoDeviceObject, 00764 sizeof(CMBATT_DEVICE_EXTENSION), 00765 &FdoDeviceObject); 00766 if (!NT_SUCCESS(Status)) 00767 { 00768 /* Fail */ 00769 if (CmBattDebug & 0xC) 00770 DbgPrint("CmBattAddAcAdapter: error (0x%x) creating Fdo\n", Status); 00771 return Status; 00772 } 00773 00774 /* Set the type and do WMI registration */ 00775 DeviceExtension = FdoDeviceObject->DeviceExtension; 00776 DeviceExtension->FdoType = CmBattAcAdapter; 00777 Status = CmBattWmiRegistration(DeviceExtension); 00778 if (!NT_SUCCESS(Status)) 00779 { 00780 /* We can go on without WMI */ 00781 if (CmBattDebug & 0xC) 00782 DbgPrint("CmBattAddBattery: Could not register as a WMI provider, status = %Lx\n", Status); 00783 } 00784 00785 /* Register with ACPI */ 00786 Status = DeviceExtension->AcpiInterface.RegisterForDeviceNotifications(DeviceExtension->AcpiInterface.Context, 00787 (PVOID)CmBattNotifyHandler, 00788 DeviceExtension); 00789 if (!(NT_SUCCESS(Status)) && (CmBattDebug & 0xC)) 00790 DbgPrint("CmBattAddAcAdapter: Could not register for power notify, status = %Lx\n", Status); 00791 00792 /* Send the first manual notification */ 00793 CmBattNotifyHandler(DeviceExtension, ACPI_BATT_NOTIFY_STATUS); 00794 return STATUS_SUCCESS; 00795 } 00796 00797 NTSTATUS 00798 NTAPI 00799 CmBattAddDevice(IN PDRIVER_OBJECT DriverObject, 00800 IN PDEVICE_OBJECT PdoDeviceObject) 00801 { 00802 NTSTATUS Status; 00803 HANDLE KeyHandle; 00804 ULONG ResultLength; 00805 UNICODE_STRING KeyString; 00806 UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)]; 00807 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PVOID)Buffer; 00808 ULONG PowerSourceType; 00809 PAGED_CODE(); 00810 if (CmBattDebug & 0x220) 00811 DbgPrint("CmBattAddDevice: Entered with pdo %x\n", PdoDeviceObject); 00812 00813 /* Make sure we have a PDO */ 00814 if (!PdoDeviceObject) 00815 { 00816 /* Should not be having as one */ 00817 if (CmBattDebug & 0x24) DbgPrint("CmBattAddDevice: Asked to do detection\n"); 00818 return STATUS_NO_MORE_ENTRIES; 00819 } 00820 00821 /* Open the driver key */ 00822 Status = IoOpenDeviceRegistryKey(PdoDeviceObject, 00823 PLUGPLAY_REGKEY_DRIVER, 00824 KEY_READ, 00825 &KeyHandle); 00826 if (!NT_SUCCESS(Status)) 00827 { 00828 if (CmBattDebug & 0xC) 00829 DbgPrint("CmBattAddDevice: Could not get the software branch: %x\n", Status); 00830 return Status; 00831 } 00832 00833 /* Read the power source type */ 00834 RtlInitUnicodeString(&KeyString, L"PowerSourceType"); 00835 Status = ZwQueryValueKey(KeyHandle, 00836 &KeyString, 00837 KeyValuePartialInformation, 00838 PartialInfo, 00839 sizeof(Buffer), 00840 &ResultLength); 00841 ZwClose(KeyHandle); 00842 if (!NT_SUCCESS(Status)) 00843 { 00844 /* We need the data, fail without it */ 00845 if (CmBattDebug & 0xC) 00846 DbgPrint("CmBattAddDevice: Could not read the power type identifier: %x\n", Status); 00847 return Status; 00848 } 00849 00850 /* Check what kind of power source this is */ 00851 PowerSourceType = *(PULONG)PartialInfo->Data; 00852 if (PowerSourceType == 1) 00853 { 00854 /* Create an AC adapter */ 00855 Status = CmBattAddAcAdapter(DriverObject, PdoDeviceObject); 00856 } 00857 else if (PowerSourceType == 0) 00858 { 00859 /* Create a battery */ 00860 Status = CmBattAddBattery(DriverObject, PdoDeviceObject); 00861 } 00862 else 00863 { 00864 /* Unknown type, fail */ 00865 if (CmBattDebug & 0xC) 00866 DbgPrint("CmBattAddDevice: Invalid POWER_SOURCE_TYPE == %d \n", PowerSourceType); 00867 return STATUS_UNSUCCESSFUL; 00868 } 00869 00870 /* Return whatever the FDO creation routine did */ 00871 return Status; 00872 } 00873 00874 /* EOF */ Generated on Sun May 27 2012 04:27:25 for ReactOS by
1.7.6.1
|