2 * PROJECT: ReactOS ACPI-Compliant Control Method Battery
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: boot/drivers/bus/acpi/cmbatt/cmbpnp.c
5 * PURPOSE: Plug-and-Play IOCTL/IRP Handling
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
13 /* FUNCTIONS ******************************************************************/
17 CmBattWaitWakeLoop(IN PDEVICE_OBJECT DeviceObject
,
18 IN UCHAR MinorFunction
,
19 IN POWER_STATE PowerState
,
21 IN PIO_STATUS_BLOCK IoStatusBlock
)
24 PCMBATT_DEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
25 if (CmBattDebug
& 0x20) DbgPrint("CmBattWaitWakeLoop: Entered.\n");
27 /* Check for success */
28 if ((NT_SUCCESS(IoStatusBlock
->Status
)) && (DeviceExtension
->WaitWakeEnable
))
30 /* Request a new power IRP */
31 if (CmBattDebug
& 2) DbgPrint("CmBattWaitWakeLoop: completed successfully\n");
32 Status
= PoRequestPowerIrp(DeviceObject
,
37 &DeviceExtension
->PowerIrp
);
39 DbgPrint("CmBattWaitWakeLoop: PoRequestPowerIrp: status = 0x%08x.\n",
44 /* Clear the power IRP, we failed */
45 if (CmBattDebug
& 0xC)
46 DbgPrint("CmBattWaitWakeLoop: failed: status = 0x%08x.\n",
47 IoStatusBlock
->Status
);
48 DeviceExtension
->PowerIrp
= NULL
;
54 CmBattIoCompletion(IN PDEVICE_OBJECT DeviceObject
,
58 if (CmBattDebug
& 2) DbgPrint("CmBattIoCompletion: Event (%x)\n", Event
);
60 /* Set the completion event */
61 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
62 return STATUS_MORE_PROCESSING_REQUIRED
;
67 CmBattGetAcpiInterfaces(IN PDEVICE_OBJECT DeviceObject
,
68 IN OUT PACPI_INTERFACE_STANDARD AcpiInterface
)
72 PIO_STACK_LOCATION IoStackLocation
;
75 /* Allocate the IRP */
76 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, 0);
80 if (CmBattDebug
& 0xC)
81 DbgPrint("CmBattGetAcpiInterfaces: Failed to allocate Irp\n");
82 return STATUS_INSUFFICIENT_RESOURCES
;
85 /* Set default error code */
86 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
89 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
90 IoStackLocation
->MinorFunction
= IRP_MN_QUERY_INTERFACE
;
91 IoStackLocation
->Parameters
.QueryInterface
.InterfaceType
= &GUID_ACPI_INTERFACE_STANDARD
;
92 IoStackLocation
->Parameters
.QueryInterface
.Size
= sizeof(ACPI_INTERFACE_STANDARD
);
93 IoStackLocation
->Parameters
.QueryInterface
.Version
= 1;
94 IoStackLocation
->Parameters
.QueryInterface
.Interface
= (PINTERFACE
)AcpiInterface
;
95 IoStackLocation
->Parameters
.QueryInterface
.InterfaceSpecificData
= NULL
;
97 /* Set default ACPI interface data */
98 AcpiInterface
->Size
= sizeof(ACPI_INTERFACE_STANDARD
);
99 AcpiInterface
->Version
= 1;
101 /* Initialize our wait event */
102 KeInitializeEvent(&Event
, SynchronizationEvent
, 0);
104 /* Set the completion routine */
105 IoCopyCurrentIrpStackLocationToNext(Irp
);
106 IoSetCompletionRoutine(Irp
,
107 (PVOID
)CmBattIoCompletion
,
114 Status
= IoCallDriver(DeviceObject
, Irp
);
115 if (Status
== STATUS_PENDING
)
117 /* Wait for completion */
118 KeWaitForSingleObject(&Event
,
123 Status
= Irp
->IoStatus
.Status
;
130 if (!(NT_SUCCESS(Status
)) && (CmBattDebug
& 0xC))
131 DbgPrint("CmBattGetAcpiInterfaces: Could not get ACPI driver interfaces, status = %x\n", Status
);
137 CmBattDestroyFdo(IN PDEVICE_OBJECT DeviceObject
)
140 if (CmBattDebug
& 0x220) DbgPrint("CmBattDestroyFdo, Battery.\n");
142 /* Delete the device */
143 IoDeleteDevice(DeviceObject
);
144 if (CmBattDebug
& 0x220) DbgPrint("CmBattDestroyFdo: done.\n");
149 CmBattRemoveDevice(IN PDEVICE_OBJECT DeviceObject
,
152 PCMBATT_DEVICE_EXTENSION DeviceExtension
;
154 DeviceExtension
= DeviceObject
->DeviceExtension
;
156 DbgPrint("CmBattRemoveDevice: CmBatt (%x), Type %d, _UID %d\n",
158 DeviceExtension
->FdoType
,
159 DeviceExtension
->DeviceId
);
161 /* Make sure it's safe to go ahead */
162 IoReleaseRemoveLockAndWait(&DeviceExtension
->RemoveLock
, 0);
164 /* Check for pending power IRP */
165 if (DeviceExtension
->PowerIrp
)
167 /* Cancel and clear */
168 IoCancelIrp(DeviceExtension
->PowerIrp
);
169 DeviceExtension
->PowerIrp
= NULL
;
172 /* Check what type of FDO is being removed */
173 Context
= DeviceExtension
->AcpiInterface
.Context
;
174 if (DeviceExtension
->FdoType
== CmBattBattery
)
176 /* Unregister battery FDO */
177 DeviceExtension
->AcpiInterface
.UnregisterForDeviceNotifications(Context
,
178 (PVOID
)CmBattNotifyHandler
);
179 CmBattWmiDeRegistration(DeviceExtension
);
180 if (!NT_SUCCESS(BatteryClassUnload(DeviceExtension
->ClassData
))) ASSERT(FALSE
);
184 /* Unregister AC adapter FDO */
185 DeviceExtension
->AcpiInterface
.UnregisterForDeviceNotifications(Context
,
186 (PVOID
)CmBattNotifyHandler
);
187 CmBattWmiDeRegistration(DeviceExtension
);
191 /* Detach and delete */
192 IoDetachDevice(DeviceExtension
->AttachedDevice
);
193 IoDeleteDevice(DeviceExtension
->DeviceObject
);
194 return STATUS_SUCCESS
;
199 CmBattPowerDispatch(IN PDEVICE_OBJECT DeviceObject
,
202 PIO_STACK_LOCATION IoStackLocation
;
203 PCMBATT_DEVICE_EXTENSION DeviceExtension
;
205 if (CmBattDebug
& 0x210) DbgPrint("CmBattPowerDispatch\n");
207 /* Get stack location and device extension */
208 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
209 DeviceExtension
= DeviceObject
->DeviceExtension
;
210 switch (IoStackLocation
->MinorFunction
)
212 case IRP_MN_WAIT_WAKE
:
213 if (CmBattDebug
& 0x10)
214 DbgPrint("CmBattPowerDispatch: IRP_MN_WAIT_WAKE\n");
217 case IRP_MN_POWER_SEQUENCE
:
218 if (CmBattDebug
& 0x10)
219 DbgPrint("CmBattPowerDispatch: IRP_MN_POWER_SEQUENCE\n");
222 case IRP_MN_QUERY_POWER
:
223 if (CmBattDebug
& 0x10)
224 DbgPrint("CmBattPowerDispatch: IRP_MN_WAIT_WAKE\n");
227 case IRP_MN_SET_POWER
:
228 if (CmBattDebug
& 0x10)
229 DbgPrint("CmBattPowerDispatch: IRP_MN_SET_POWER type: %d, State: %d \n",
230 IoStackLocation
->Parameters
.Power
.Type
,
231 IoStackLocation
->Parameters
.Power
.State
);
237 DbgPrint("CmBattPowerDispatch: minor %d\n", IoStackLocation
->MinorFunction
);
241 /* Start the next IRP and see if we're attached */
242 PoStartNextPowerIrp(Irp
);
243 if (DeviceExtension
->AttachedDevice
)
246 IoSkipCurrentIrpStackLocation(Irp
);
247 Status
= PoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
251 /* Complete the request here */
252 Status
= Irp
->IoStatus
.Status
;
253 IofCompleteRequest(Irp
, IO_NO_INCREMENT
);
262 CmBattPnpDispatch(IN PDEVICE_OBJECT DeviceObject
,
265 PIO_STACK_LOCATION IoStackLocation
;
266 PCMBATT_DEVICE_EXTENSION DeviceExtension
;
271 /* Get stack location and device extension */
272 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
273 DeviceExtension
= DeviceObject
->DeviceExtension
;
275 /* Set default error */
276 Status
= STATUS_NOT_SUPPORTED
;
278 /* Try to acquire the lock before doing anything */
279 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, 0);
280 if (!NT_SUCCESS(Status
))
282 /* Complete the request */
283 Irp
->IoStatus
.Status
= STATUS_DEVICE_REMOVED
;
284 IofCompleteRequest(Irp
, IO_NO_INCREMENT
);
285 return STATUS_DEVICE_REMOVED
;
288 /* What's the operation? */
289 switch (IoStackLocation
->MinorFunction
)
291 case IRP_MN_QUERY_PNP_DEVICE_STATE
:
293 /* Initialize our wait event */
294 KeInitializeEvent(&Event
, SynchronizationEvent
, 0);
296 /* Set the completion routine */
297 IoCopyCurrentIrpStackLocationToNext(Irp
);
298 IoSetCompletionRoutine(Irp
,
299 (PVOID
)CmBattIoCompletion
,
305 /* Now call ACPI to inherit its PnP Device State */
306 Status
= IoCallDriver(DeviceObject
, Irp
);
307 if (Status
== STATUS_PENDING
)
309 /* Wait for completion */
310 KeWaitForSingleObject(&Event
,
315 Status
= Irp
->IoStatus
.Status
;
318 /* However, a battery CAN be disabled */
319 Irp
->IoStatus
.Information
&= ~PNP_DEVICE_NOT_DISABLEABLE
;
321 /* Release the remove lock and complete the request */
322 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
323 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
326 case IRP_MN_SURPRISE_REMOVAL
:
327 if (CmBattDebug
& 0x20)
328 DbgPrint("CmBattPnpDispatch: IRP_MN_SURPRISE_REMOVAL\n");
330 /* Lock the device extension and set the handle count to invalid */
331 ExAcquireFastMutex(&DeviceExtension
->FastMutex
);
332 DeviceExtension
->HandleCount
= -1;
333 ExReleaseFastMutex(&DeviceExtension
->FastMutex
);
334 Status
= STATUS_SUCCESS
;
337 case IRP_MN_START_DEVICE
:
338 if (CmBattDebug
& 0x20)
339 DbgPrint("CmBattPnpDispatch: IRP_MN_START_DEVICE\n");
341 /* Mark the extension as started */
342 if (DeviceExtension
->FdoType
== CmBattBattery
) DeviceExtension
->Started
= TRUE
;
343 Status
= STATUS_SUCCESS
;
346 case IRP_MN_STOP_DEVICE
:
347 if (CmBattDebug
& 0x20)
348 DbgPrint("CmBattPnpDispatch: IRP_MN_STOP_DEVICE\n");
350 /* Mark the extension as stopped */
351 if (DeviceExtension
->FdoType
== CmBattBattery
) DeviceExtension
->Started
= FALSE
;
352 Status
= STATUS_SUCCESS
;
355 case IRP_MN_QUERY_REMOVE_DEVICE
:
356 if (CmBattDebug
& 0x20)
357 DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_REMOVE_DEVICE\n");
359 /* Lock the extension and get the current handle count */
360 ExAcquireFastMutex(&DeviceExtension
->FastMutex
);
361 if (DeviceExtension
->HandleCount
== 0)
363 /* No handles. Mark it as invalid since it'll be removed */
364 DeviceExtension
->HandleCount
= -1;
365 Status
= STATUS_SUCCESS
;
367 else if (DeviceExtension
->HandleCount
== -1)
369 /* Don't do anything, but this is strange since it's already removed */
370 Status
= STATUS_SUCCESS
;
372 DbgPrint("CmBattPnpDispatch: Recieved two consecutive QUERY_REMOVE requests.\n");
376 /* Fail because there's still open handles */
377 Status
= STATUS_UNSUCCESSFUL
;
380 /* Release the lock and return */
381 ExReleaseFastMutex(&DeviceExtension
->FastMutex
);
384 case IRP_MN_REMOVE_DEVICE
:
385 if (CmBattDebug
& 0x20)
386 DbgPrint("CmBattPnpDispatch: IRP_MN_REMOVE_DEVICE\n");
388 /* Call the remove code */
389 Status
= CmBattRemoveDevice(DeviceObject
, Irp
);
392 case IRP_MN_CANCEL_REMOVE_DEVICE
:
393 if (CmBattDebug
& 0x20)
394 DbgPrint("CmBattPnpDispatch: IRP_MN_CANCEL_REMOVE_DEVICE\n");
396 /* Lock the extension and get the handle count */
397 ExAcquireFastMutex(&DeviceExtension
->FastMutex
);
398 if (DeviceExtension
->HandleCount
== -1)
400 /* A remove was in progress, set the handle count back to 0 */
401 DeviceExtension
->HandleCount
= 0;
403 else if (CmBattDebug
& 2)
405 /* Nop, but warn about it */
406 DbgPrint("CmBattPnpDispatch: Received CANCEL_REMOVE when OpenCount == %x\n",
407 DeviceExtension
->HandleCount
);
410 /* Return success in all cases, and release the lock */
411 Status
= STATUS_SUCCESS
;
412 ExReleaseFastMutex(&DeviceExtension
->FastMutex
);
415 case IRP_MN_QUERY_STOP_DEVICE
:
416 if (CmBattDebug
& 0x20)
417 DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_STOP_DEVICE\n");
419 /* There's no real support for this */
420 Status
= STATUS_NOT_IMPLEMENTED
;
423 case IRP_MN_CANCEL_STOP_DEVICE
:
424 if (CmBattDebug
& 0x20)
425 DbgPrint("CmBattPnpDispatch: IRP_MN_CANCEL_STOP_DEVICE\n");
427 /* There's no real support for this */
428 Status
= STATUS_NOT_IMPLEMENTED
;
431 case IRP_MN_QUERY_CAPABILITIES
:
433 /* Initialize our wait event */
434 KeInitializeEvent(&Event
, SynchronizationEvent
, 0);
436 /* Set the completion routine */
437 IoCopyCurrentIrpStackLocationToNext(Irp
);
438 IoSetCompletionRoutine(Irp
,
439 (PVOID
)CmBattIoCompletion
,
446 Status
= IoCallDriver(DeviceObject
, Irp
);
447 if (Status
== STATUS_PENDING
)
449 /* Wait for completion */
450 KeWaitForSingleObject(&Event
,
455 Status
= Irp
->IoStatus
.Status
;
458 /* Get the wake power state */
459 DeviceExtension
->PowerState
.SystemState
= IoStackLocation
->Parameters
.DeviceCapabilities
.Capabilities
->SystemWake
;
460 if (CmBattDebug
& 0x20)
461 DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES %d Capabilities->SystemWake = %x\n",
462 DeviceExtension
->FdoType
,
463 DeviceExtension
->PowerState
);
465 /* Check if it's invalid */
466 if (DeviceExtension
->PowerState
.SystemState
== PowerSystemUnspecified
)
468 /* Wait wake is not supported in this scenario */
469 DeviceExtension
->WaitWakeEnable
= FALSE
;
470 if (CmBattDebug
& 0x20)
471 DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES Wake not supported.\n");
473 else if (!(DeviceExtension
->PowerIrp
) &&
474 (DeviceExtension
->WaitWakeEnable
))
476 /* If it was requested in the registry, request the power IRP for it */
477 PoRequestPowerIrp(DeviceExtension
->DeviceObject
,
479 DeviceExtension
->PowerState
,
482 &DeviceExtension
->PowerIrp
);
483 if (CmBattDebug
& 0x20)
484 DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES wait/Wake irp sent.\n");
487 /* Release the remove lock and complete the request */
488 IofCompleteRequest(Irp
, IO_NO_INCREMENT
);
489 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
494 if (CmBattDebug
& 0x20)
495 DbgPrint("CmBattPnpDispatch: Unimplemented minor %0x\n",
496 IoStackLocation
->MinorFunction
);
500 /* Release the remove lock */
501 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
503 /* Set IRP status if we have one */
504 if (Status
!= STATUS_NOT_SUPPORTED
) Irp
->IoStatus
.Status
= Status
;
506 /* Did someone pick it up? */
507 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_NOT_SUPPORTED
))
509 /* Still unsupported, try ACPI */
510 IoSkipCurrentIrpStackLocation(Irp
);
511 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
515 /* Complete the request */
516 Status
= Irp
->IoStatus
.Status
;
517 IofCompleteRequest(Irp
, IO_NO_INCREMENT
);
520 /* Release the remove lock and return status */
526 CmBattCreateFdo(IN PDRIVER_OBJECT DriverObject
,
527 IN PDEVICE_OBJECT DeviceObject
,
528 IN ULONG DeviceExtensionSize
,
529 IN PDEVICE_OBJECT
*NewDeviceObject
)
531 PDEVICE_OBJECT FdoDeviceObject
;
533 PCMBATT_DEVICE_EXTENSION FdoExtension
;
534 UCHAR Buffer
[sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(ULONG
)];
535 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
= (PVOID
)Buffer
;
537 UNICODE_STRING KeyString
;
541 if (CmBattDebug
& 0x220) DbgPrint("CmBattCreateFdo: Entered\n");
544 Status
= CmBattGetUniqueId(DeviceObject
, &UniqueId
);
545 if (!NT_SUCCESS(Status
))
550 DbgPrint("CmBattCreateFdo: Error %x from _UID, assuming unit #0\n", Status
);
554 Status
= IoCreateDevice(DriverObject
,
558 FILE_DEVICE_SECURE_OPEN
,
561 if (!NT_SUCCESS(Status
))
564 if (CmBattDebug
& 0xC)
565 DbgPrint("CmBattCreateFdo: error (0x%x) creating device object\n", Status
);
570 FdoDeviceObject
->Flags
|= DO_BUFFERED_IO
;
571 FdoDeviceObject
->Flags
|= DO_MAP_IO_BUFFER
;
572 FdoDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
574 /* Initialize the extension */
575 FdoExtension
= FdoDeviceObject
->DeviceExtension
;
576 RtlZeroMemory(FdoExtension
, DeviceExtensionSize
);
577 FdoExtension
->DeviceObject
= FdoDeviceObject
;
578 FdoExtension
->FdoDeviceObject
= FdoDeviceObject
;
579 FdoExtension
->PdoDeviceObject
= DeviceObject
;
582 FdoExtension
->AttachedDevice
= IoAttachDeviceToDeviceStack(FdoDeviceObject
,
584 if (!FdoExtension
->AttachedDevice
)
586 /* Destroy and fail */
587 CmBattDestroyFdo(FdoExtension
->FdoDeviceObject
);
588 if (CmBattDebug
& 0xC)
589 DbgPrint("CmBattCreateFdo: IoAttachDeviceToDeviceStack failed.\n");
590 return STATUS_UNSUCCESSFUL
;
593 /* Get ACPI interface for EVAL */
594 Status
= CmBattGetAcpiInterfaces(FdoExtension
->AttachedDevice
,
595 &FdoExtension
->AcpiInterface
);
596 if (!FdoExtension
->AttachedDevice
)
598 /* Detach, destroy, and fail */
599 IoDetachDevice(FdoExtension
->AttachedDevice
);
600 CmBattDestroyFdo(FdoExtension
->FdoDeviceObject
);
601 if (CmBattDebug
& 0xC)
602 DbgPrint("CmBattCreateFdo: Could not get ACPI interfaces: %x\n", Status
);
603 return STATUS_UNSUCCESSFUL
;
606 /* Setup the rest of the extension */
607 ExInitializeFastMutex(&FdoExtension
->FastMutex
);
608 IoInitializeRemoveLock(&FdoExtension
->RemoveLock
, 0, 0, 0);
609 FdoExtension
->HandleCount
= 0;
610 FdoExtension
->WaitWakeEnable
= FALSE
;
611 FdoExtension
->DeviceId
= UniqueId
;
612 FdoExtension
->DeviceName
= NULL
;
613 FdoExtension
->DelayNotification
= FALSE
;
614 FdoExtension
->ArFlag
= 0;
616 /* Open the device key */
617 Status
= IoOpenDeviceRegistryKey(DeviceObject
,
618 PLUGPLAY_REGKEY_DEVICE
,
621 if (NT_SUCCESS(Status
))
623 /* Read wait wake value */
624 RtlInitUnicodeString(&KeyString
, L
"WaitWakeEnabled");
625 Status
= ZwQueryValueKey(KeyHandle
,
627 KeyValuePartialInformation
,
631 if (NT_SUCCESS(Status
))
634 FdoExtension
->WaitWakeEnable
= *(PULONG
)PartialInfo
->Data
;
637 /* Close the handle */
641 /* Return success and the new FDO */
642 *NewDeviceObject
= FdoDeviceObject
;
643 if (CmBattDebug
& 0x220)
644 DbgPrint("CmBattCreateFdo: Created FDO %x\n", FdoDeviceObject
);
645 return STATUS_SUCCESS
;
650 CmBattAddBattery(IN PDRIVER_OBJECT DriverObject
,
651 IN PDEVICE_OBJECT DeviceObject
)
653 BATTERY_MINIPORT_INFO MiniportInfo
;
655 PDEVICE_OBJECT FdoDeviceObject
;
656 PCMBATT_DEVICE_EXTENSION FdoExtension
;
658 if (CmBattDebug
& 0x220)
659 DbgPrint("CmBattAddBattery: pdo %x\n", DeviceObject
);
662 Status
= CmBattCreateFdo(DriverObject
,
664 sizeof(CMBATT_DEVICE_EXTENSION
),
666 if (!NT_SUCCESS(Status
))
668 if (CmBattDebug
& 0xC)
669 DbgPrint("CmBattAddBattery: error (0x%x) creating Fdo\n", Status
);
673 /* Build the FDO extensio, check if we support trip points */
674 FdoExtension
= FdoDeviceObject
->DeviceExtension
;
675 FdoExtension
->FdoType
= CmBattBattery
;
676 FdoExtension
->Started
= 0;
677 FdoExtension
->NotifySent
= TRUE
;
678 InterlockedExchange(&FdoExtension
->ArLockValue
, 0);
679 FdoExtension
->TripPointValue
= BATTERY_UNKNOWN_CAPACITY
;
680 FdoExtension
->Tag
= 0;
681 FdoExtension
->InterruptTime
= KeQueryInterruptTime();
682 FdoExtension
->TripPointSet
= CmBattSetTripPpoint(FdoExtension
, 0) !=
683 STATUS_OBJECT_NAME_NOT_FOUND
;
685 /* Setup the battery miniport information structure */
686 RtlZeroMemory(&MiniportInfo
, sizeof(MiniportInfo
));
687 MiniportInfo
.Pdo
= DeviceObject
;
688 MiniportInfo
.MajorVersion
= BATTERY_CLASS_MAJOR_VERSION
;
689 MiniportInfo
.MinorVersion
= BATTERY_CLASS_MINOR_VERSION
;
690 MiniportInfo
.Context
= FdoExtension
;
691 MiniportInfo
.QueryTag
= (PVOID
)CmBattQueryTag
;
692 MiniportInfo
.QueryInformation
= (PVOID
)CmBattQueryInformation
;
693 MiniportInfo
.SetInformation
= NULL
;
694 MiniportInfo
.QueryStatus
= (PVOID
)CmBattQueryStatus
;
695 MiniportInfo
.SetStatusNotify
= (PVOID
)CmBattSetStatusNotify
;
696 MiniportInfo
.DisableStatusNotify
= (PVOID
)CmBattDisableStatusNotify
;
697 MiniportInfo
.DeviceName
= FdoExtension
->DeviceName
;
699 /* Register with the class driver */
700 Status
= BatteryClassInitializeDevice(&MiniportInfo
, &FdoExtension
->ClassData
);
701 if (!NT_SUCCESS(Status
))
703 IoDetachDevice(FdoExtension
->AttachedDevice
);
704 CmBattDestroyFdo(FdoExtension
->FdoDeviceObject
);
705 if (CmBattDebug
& 0xC)
706 DbgPrint("CmBattAddBattery: error (0x%x) registering with class\n", Status
);
711 Status
= CmBattWmiRegistration(FdoExtension
);
712 if (!NT_SUCCESS(Status
))
714 if (CmBattDebug
& 0xC)
715 DbgPrint("CmBattAddBattery: Could not register as a WMI provider, status = %Lx\n", Status
);
720 Status
= FdoExtension
->AcpiInterface
.RegisterForDeviceNotifications(FdoExtension
->AcpiInterface
.Context
,
721 (PVOID
)CmBattNotifyHandler
,
723 if (!NT_SUCCESS(Status
))
725 CmBattWmiDeRegistration(FdoExtension
);
726 BatteryClassUnload(FdoExtension
->ClassData
);
727 IoDetachDevice(FdoExtension
->AttachedDevice
);
728 CmBattDestroyFdo(FdoExtension
->FdoDeviceObject
);
729 if (CmBattDebug
& 0xC)
730 DbgPrint("CmBattAddBattery: Could not register for battery notify, status = %Lx\n", Status
);
739 CmBattAddAcAdapter(IN PDRIVER_OBJECT DriverObject
,
740 IN PDEVICE_OBJECT PdoDeviceObject
)
742 PDEVICE_OBJECT FdoDeviceObject
;
744 PCMBATT_DEVICE_EXTENSION DeviceExtension
;
746 if (CmBattDebug
& 0x220)
747 DbgPrint("CmBattAddAcAdapter: pdo %x\n", PdoDeviceObject
);
749 /* Check if we already have an AC adapter */
752 /* Don't do anything */
753 if (CmBattDebug
& 0xC)
754 DbgPrint("CmBatt: Second AC adapter found. Current version of driver only supports 1 aadapter.\n");
758 /* Set this as the AC adapter's PDO */
759 AcAdapterPdo
= PdoDeviceObject
;
762 /* Create the FDO for the adapter */
763 Status
= CmBattCreateFdo(DriverObject
,
765 sizeof(CMBATT_DEVICE_EXTENSION
),
767 if (!NT_SUCCESS(Status
))
770 if (CmBattDebug
& 0xC)
771 DbgPrint("CmBattAddAcAdapter: error (0x%x) creating Fdo\n", Status
);
775 /* Set the type and do WMI registration */
776 DeviceExtension
= FdoDeviceObject
->DeviceExtension
;
777 DeviceExtension
->FdoType
= CmBattAcAdapter
;
778 Status
= CmBattWmiRegistration(DeviceExtension
);
779 if (!NT_SUCCESS(Status
))
781 /* We can go on without WMI */
782 if (CmBattDebug
& 0xC)
783 DbgPrint("CmBattAddBattery: Could not register as a WMI provider, status = %Lx\n", Status
);
786 /* Register with ACPI */
787 Status
= DeviceExtension
->AcpiInterface
.RegisterForDeviceNotifications(DeviceExtension
->AcpiInterface
.Context
,
788 (PVOID
)CmBattNotifyHandler
,
790 if (!(NT_SUCCESS(Status
)) && (CmBattDebug
& 0xC))
791 DbgPrint("CmBattAddAcAdapter: Could not register for power notify, status = %Lx\n", Status
);
793 /* Send the first manual notification */
794 CmBattNotifyHandler(DeviceExtension
, ACPI_BATT_NOTIFY_STATUS
);
795 return STATUS_SUCCESS
;
800 CmBattAddDevice(IN PDRIVER_OBJECT DriverObject
,
801 IN PDEVICE_OBJECT PdoDeviceObject
)
806 UNICODE_STRING KeyString
;
807 UCHAR Buffer
[sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(ULONG
)];
808 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
= (PVOID
)Buffer
;
809 ULONG PowerSourceType
;
811 if (CmBattDebug
& 0x220)
812 DbgPrint("CmBattAddDevice: Entered with pdo %x\n", PdoDeviceObject
);
814 /* Make sure we have a PDO */
815 if (!PdoDeviceObject
)
817 /* Should not be having as one */
818 if (CmBattDebug
& 0x24) DbgPrint("CmBattAddDevice: Asked to do detection\n");
819 return STATUS_NO_MORE_ENTRIES
;
822 /* Open the driver key */
823 Status
= IoOpenDeviceRegistryKey(PdoDeviceObject
,
824 PLUGPLAY_REGKEY_DRIVER
,
827 if (!NT_SUCCESS(Status
))
829 if (CmBattDebug
& 0xC)
830 DbgPrint("CmBattAddDevice: Could not get the software branch: %x\n", Status
);
834 /* Read the power source type */
835 RtlInitUnicodeString(&KeyString
, L
"PowerSourceType");
836 Status
= ZwQueryValueKey(KeyHandle
,
838 KeyValuePartialInformation
,
843 if (!NT_SUCCESS(Status
))
845 /* We need the data, fail without it */
846 if (CmBattDebug
& 0xC)
847 DbgPrint("CmBattAddDevice: Could not read the power type identifier: %x\n", Status
);
851 /* Check what kind of power source this is */
852 PowerSourceType
= *(PULONG
)PartialInfo
->Data
;
853 if (PowerSourceType
== 1)
855 /* Create an AC adapter */
856 Status
= CmBattAddAcAdapter(DriverObject
, PdoDeviceObject
);
858 else if (PowerSourceType
== 0)
860 /* Create a battery */
861 Status
= CmBattAddBattery(DriverObject
, PdoDeviceObject
);
865 /* Unknown type, fail */
866 if (CmBattDebug
& 0xC)
867 DbgPrint("CmBattAddDevice: Invalid POWER_SOURCE_TYPE == %d \n", PowerSourceType
);
868 return STATUS_UNSUCCESSFUL
;
871 /* Return whatever the FDO creation routine did */