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 CmBattIoCompletion(PDEVICE_OBJECT DeviceObject
,
22 return STATUS_NOT_IMPLEMENTED
;
27 CmBattGetAcpiInterfaces(PDEVICE_OBJECT DeviceObject
,
28 PACPI_INTERFACE_STANDARD AcpiInterface
)
31 return STATUS_NOT_IMPLEMENTED
;
36 CmBattDestroyFdo(IN PDEVICE_OBJECT DeviceObject
)
39 if (CmBattDebug
& 0x220) DbgPrint("CmBattDestroyFdo, Battery.\n");
41 /* Delete the device */
42 IoDeleteDevice(DeviceObject
);
43 if (CmBattDebug
& 0x220) DbgPrint("CmBattDestroyFdo: done.\n");
48 CmBattRemoveDevice(IN PDEVICE_OBJECT DeviceObject
,
51 PCMBATT_DEVICE_EXTENSION DeviceExtension
;
53 DeviceExtension
= DeviceObject
->DeviceExtension
;
55 DbgPrint("CmBattRemoveDevice: CmBatt (%x), Type %d, _UID %d\n",
57 DeviceExtension
->FdoType
,
58 DeviceExtension
->DeviceId
);
60 /* Make sure it's safe to go ahead */
61 IoReleaseRemoveLockAndWait(&DeviceExtension
->RemoveLock
, 0);
63 /* Check for pending power IRP */
64 if (DeviceExtension
->PowerIrp
)
66 /* Cancel and clear */
67 IoCancelIrp(DeviceExtension
->PowerIrp
);
68 DeviceExtension
->PowerIrp
= NULL
;
71 /* Check what type of FDO is being removed */
72 Context
= DeviceExtension
->AcpiInterface
.Context
;
73 if (DeviceExtension
->FdoType
== CmBattBattery
)
75 /* Unregister battery FDO */
76 DeviceExtension
->AcpiInterface
.UnregisterForDeviceNotifications(Context
,
77 (PVOID
)CmBattNotifyHandler
);
78 CmBattWmiDeRegistration(DeviceExtension
);
79 if (!NT_SUCCESS(BatteryClassUnload(DeviceExtension
->ClassData
))) ASSERT(FALSE
);
83 /* Unregister AC adapter FDO */
84 DeviceExtension
->AcpiInterface
.UnregisterForDeviceNotifications(Context
,
85 (PVOID
)CmBattNotifyHandler
);
86 CmBattWmiDeRegistration(DeviceExtension
);
90 /* Detach and delete */
91 IoDetachDevice(DeviceExtension
->AttachedDevice
);
92 IoDeleteDevice(DeviceExtension
->DeviceObject
);
93 return STATUS_SUCCESS
;
98 CmBattPowerDispatch(PDEVICE_OBJECT DeviceObject
,
102 return STATUS_NOT_IMPLEMENTED
;
107 CmBattPnpDispatch(PDEVICE_OBJECT DeviceObject
,
111 return STATUS_NOT_IMPLEMENTED
;
116 CmBattCreateFdo(IN PDRIVER_OBJECT DriverObject
,
117 IN PDEVICE_OBJECT DeviceObject
,
118 IN ULONG DeviceExtensionSize
,
119 IN PDEVICE_OBJECT
*NewDeviceObject
)
121 PDEVICE_OBJECT FdoDeviceObject
;
123 PCMBATT_DEVICE_EXTENSION FdoExtension
;
124 UCHAR Buffer
[sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(ULONG
)];
125 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
= (PVOID
)Buffer
;
127 UNICODE_STRING KeyString
;
131 if (CmBattDebug
& 0x220) DbgPrint("CmBattCreateFdo: Entered\n");
134 Status
= CmBattGetUniqueId(DeviceObject
, &UniqueId
);
135 if (!NT_SUCCESS(Status
))
140 DbgPrint("CmBattCreateFdo: Error %x from _UID, assuming unit #0\n", Status
);
144 Status
= IoCreateDevice(DriverObject
,
148 FILE_DEVICE_SECURE_OPEN
,
151 if (!NT_SUCCESS(Status
))
154 if (CmBattDebug
& 0xC)
155 DbgPrint("CmBattCreateFdo: error (0x%x) creating device object\n", Status
);
160 FdoDeviceObject
->Flags
|= DO_BUFFERED_IO
;
161 FdoDeviceObject
->Flags
|= DO_MAP_IO_BUFFER
;
162 FdoDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
164 /* Initialize the extension */
165 FdoExtension
= FdoDeviceObject
->DeviceExtension
;
166 RtlZeroMemory(FdoExtension
, DeviceExtensionSize
);
167 FdoExtension
->DeviceObject
= FdoDeviceObject
;
168 FdoExtension
->FdoDeviceObject
= FdoDeviceObject
;
169 FdoExtension
->PdoDeviceObject
= DeviceObject
;
172 FdoExtension
->AttachedDevice
= IoAttachDeviceToDeviceStack(FdoDeviceObject
,
174 if (!FdoExtension
->AttachedDevice
)
176 /* Destroy and fail */
177 CmBattDestroyFdo(FdoExtension
->FdoDeviceObject
);
178 if (CmBattDebug
& 0xC)
179 DbgPrint("CmBattCreateFdo: IoAttachDeviceToDeviceStack failed.\n");
180 return STATUS_UNSUCCESSFUL
;
183 /* Get ACPI interface for EVAL */
184 Status
= CmBattGetAcpiInterfaces(FdoExtension
->AttachedDevice
,
185 &FdoExtension
->AcpiInterface
);
186 if (!FdoExtension
->AttachedDevice
)
188 /* Detach, destroy, and fail */
189 IoDetachDevice(FdoExtension
->AttachedDevice
);
190 CmBattDestroyFdo(FdoExtension
->FdoDeviceObject
);
191 if (CmBattDebug
& 0xC)
192 DbgPrint("CmBattCreateFdo: Could not get ACPI interfaces: %x\n", Status
);
193 return STATUS_UNSUCCESSFUL
;
196 /* Setup the rest of the extension */
197 ExInitializeFastMutex(&FdoExtension
->FastMutex
);
198 IoInitializeRemoveLock(&FdoExtension
->RemoveLock
, 0, 0, 0);
199 FdoExtension
->HandleCount
= 0;
200 FdoExtension
->WaitWakeEnable
= FALSE
;
201 FdoExtension
->DeviceId
= UniqueId
;
202 FdoExtension
->DeviceName
= NULL
;
203 FdoExtension
->DelayNotification
= FALSE
;
204 FdoExtension
->ArFlag
= 0;
206 /* Open the device key */
207 Status
= IoOpenDeviceRegistryKey(DeviceObject
,
208 PLUGPLAY_REGKEY_DEVICE
,
211 if (NT_SUCCESS(Status
))
213 /* Read wait wake value */
214 RtlInitUnicodeString(&KeyString
, L
"WaitWakeEnabled");
215 Status
= ZwQueryValueKey(KeyHandle
,
217 KeyValuePartialInformation
,
221 if (NT_SUCCESS(Status
))
224 FdoExtension
->WaitWakeEnable
= *(PULONG
)PartialInfo
->Data
;
227 /* Close the handle */
231 /* Return success and the new FDO */
232 *NewDeviceObject
= FdoDeviceObject
;
233 if (CmBattDebug
& 0x220)
234 DbgPrint("CmBattCreateFdo: Created FDO %x\n", FdoDeviceObject
);
235 return STATUS_SUCCESS
;
240 CmBattAddBattery(IN PDRIVER_OBJECT DriverObject
,
241 IN PDEVICE_OBJECT DeviceObject
)
243 BATTERY_MINIPORT_INFO MiniportInfo
;
245 PDEVICE_OBJECT FdoDeviceObject
;
246 PCMBATT_DEVICE_EXTENSION FdoExtension
;
248 if (CmBattDebug
& 0x220)
249 DbgPrint("CmBattAddBattery: pdo %x\n", DeviceObject
);
251 Status
= CmBattCreateFdo(DriverObject
,
253 sizeof(CMBATT_DEVICE_EXTENSION
),
255 if (!NT_SUCCESS(Status
))
257 if (CmBattDebug
& 0xC)
258 DbgPrint("CmBattAddBattery: error (0x%x) creating Fdo\n", Status
);
262 /* Build the FDO extensio, check if we support trip points */
263 FdoExtension
= FdoDeviceObject
->DeviceExtension
;
264 FdoExtension
->FdoType
= CmBattBattery
;
265 FdoExtension
->Started
= 0;
266 FdoExtension
->NotifySent
= TRUE
;
267 InterlockedExchange(&FdoExtension
->ArLockValue
, 0);
268 FdoExtension
->TripPointValue
= BATTERY_UNKNOWN_CAPACITY
;
269 FdoExtension
->Tag
= 0;
270 FdoExtension
->InterruptTime
= KeQueryInterruptTime();
271 FdoExtension
->TripPointSet
= CmBattSetTripPpoint(FdoExtension
, 0) !=
272 STATUS_OBJECT_NAME_NOT_FOUND
;
274 /* Setup the battery miniport information structure */
275 RtlZeroMemory(&MiniportInfo
, sizeof(MiniportInfo
));
276 MiniportInfo
.Pdo
= DeviceObject
;
277 MiniportInfo
.MajorVersion
= BATTERY_CLASS_MAJOR_VERSION
;
278 MiniportInfo
.MinorVersion
= BATTERY_CLASS_MINOR_VERSION
;
279 MiniportInfo
.Context
= FdoExtension
;
280 MiniportInfo
.QueryTag
= (PVOID
)CmBattQueryTag
;
281 MiniportInfo
.QueryInformation
= (PVOID
)CmBattQueryInformation
;
282 MiniportInfo
.SetInformation
= NULL
;
283 MiniportInfo
.QueryStatus
= (PVOID
)CmBattQueryStatus
;
284 MiniportInfo
.SetStatusNotify
= (PVOID
)CmBattSetStatusNotify
;
285 MiniportInfo
.DisableStatusNotify
= (PVOID
)CmBattDisableStatusNotify
;
286 MiniportInfo
.DeviceName
= FdoExtension
->DeviceName
;
288 /* Register with the class driver */
289 Status
= BatteryClassInitializeDevice(&MiniportInfo
, &FdoExtension
->ClassData
);
290 if (!NT_SUCCESS(Status
))
292 IoDetachDevice(FdoExtension
->AttachedDevice
);
293 CmBattDestroyFdo(FdoExtension
->FdoDeviceObject
);
294 if (CmBattDebug
& 0xC)
295 DbgPrint("CmBattAddBattery: error (0x%x) registering with class\n", Status
);
300 Status
= CmBattWmiRegistration(FdoExtension
);
301 if (!NT_SUCCESS(Status
))
303 if (CmBattDebug
& 0xC)
304 DbgPrint("CmBattAddBattery: Could not register as a WMI provider, status = %Lx\n", Status
);
309 Status
= FdoExtension
->AcpiInterface
.RegisterForDeviceNotifications(FdoExtension
->AcpiInterface
.Context
,
310 (PVOID
)CmBattNotifyHandler
,
312 if (!NT_SUCCESS(Status
))
314 CmBattWmiDeRegistration(FdoExtension
);
315 BatteryClassUnload(FdoExtension
->ClassData
);
316 IoDetachDevice(FdoExtension
->AttachedDevice
);
317 CmBattDestroyFdo(FdoExtension
->FdoDeviceObject
);
318 if (CmBattDebug
& 0xC)
319 DbgPrint("CmBattAddBattery: Could not register for battery notify, status = %Lx\n", Status
);
328 CmBattAddAcAdapter(IN PDRIVER_OBJECT DriverObject
,
329 IN PDEVICE_OBJECT PdoDeviceObject
)
331 PDEVICE_OBJECT FdoDeviceObject
;
333 PCMBATT_DEVICE_EXTENSION DeviceExtension
;
335 if (CmBattDebug
& 0x220)
336 DbgPrint("CmBattAddAcAdapter: pdo %x\n", PdoDeviceObject
);
338 /* Check if we already have an AC adapter */
341 /* Don't do anything */
342 if (CmBattDebug
& 0xC)
343 DbgPrint("CmBatt: Second AC adapter found. Current version of driver only supports 1 aadapter.\n");
347 /* Set this as the AC adapter's PDO */
348 AcAdapterPdo
= PdoDeviceObject
;
351 /* Create the FDO for the adapter */
352 Status
= CmBattCreateFdo(DriverObject
,
354 sizeof(CMBATT_DEVICE_EXTENSION
),
356 if (!NT_SUCCESS(Status
))
359 if (CmBattDebug
& 0xC)
360 DbgPrint("CmBattAddAcAdapter: error (0x%x) creating Fdo\n", Status
);
364 /* Set the type and do WMI registration */
365 DeviceExtension
= FdoDeviceObject
->DeviceExtension
;
366 DeviceExtension
->FdoType
= CmBattAcAdapter
;
367 Status
= CmBattWmiRegistration(DeviceExtension
);
368 if (!NT_SUCCESS(Status
))
370 /* We can go on without WMI */
371 if (CmBattDebug
& 0xC)
372 DbgPrint("CmBattAddBattery: Could not register as a WMI provider, status = %Lx\n", Status
);
375 /* Register with ACPI */
376 Status
= DeviceExtension
->AcpiInterface
.RegisterForDeviceNotifications(DeviceExtension
->AcpiInterface
.Context
,
377 (PVOID
)CmBattNotifyHandler
,
379 if (!(NT_SUCCESS(Status
)) && (CmBattDebug
& 0xC))
380 DbgPrint("CmBattAddAcAdapter: Could not register for power notify, status = %Lx\n", Status
);
382 /* Send the first manual notification */
383 CmBattNotifyHandler(DeviceExtension
, ACPI_BATT_NOTIFY_STATUS
);
384 return STATUS_SUCCESS
;
389 CmBattAddDevice(IN PDRIVER_OBJECT DriverObject
,
390 IN PDEVICE_OBJECT PdoDeviceObject
)
395 UNICODE_STRING KeyString
;
396 UCHAR Buffer
[sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(ULONG
)];
397 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
= (PVOID
)Buffer
;
398 ULONG PowerSourceType
;
400 if (CmBattDebug
& 0x220)
401 DbgPrint("CmBattAddDevice: Entered with pdo %x\n", PdoDeviceObject
);
403 /* Make sure we have a PDO */
404 if (!PdoDeviceObject
)
406 /* Should not be having as one */
407 if (CmBattDebug
& 0x24) DbgPrint("CmBattAddDevice: Asked to do detection\n");
408 return STATUS_NO_MORE_ENTRIES
;
411 /* Open the driver key */
412 Status
= IoOpenDeviceRegistryKey(PdoDeviceObject
,
413 PLUGPLAY_REGKEY_DRIVER
,
416 if (!NT_SUCCESS(Status
))
418 if (CmBattDebug
& 0xC)
419 DbgPrint("CmBattAddDevice: Could not get the software branch: %x\n", Status
);
423 /* Read the power source type */
424 RtlInitUnicodeString(&KeyString
, L
"PowerSourceType");
425 Status
= ZwQueryValueKey(KeyHandle
,
427 KeyValuePartialInformation
,
432 if (!NT_SUCCESS(Status
))
434 /* We need the data, fail without it */
435 if (CmBattDebug
& 0xC)
436 DbgPrint("CmBattAddDevice: Could not read the power type identifier: %x\n", Status
);
440 /* Check what kind of power source this is */
441 PowerSourceType
= *(PULONG
)PartialInfo
->Data
;
442 if (PowerSourceType
== 1)
444 /* Create an AC adapter */
445 Status
= CmBattAddAcAdapter(DriverObject
, PdoDeviceObject
);
447 else if (PowerSourceType
== 0)
449 /* Create a battery */
450 Status
= CmBattAddBattery(DriverObject
, PdoDeviceObject
);
454 /* Unknown type, fail */
455 if (CmBattDebug
& 0xC)
456 DbgPrint("CmBattAddDevice: Invalid POWER_SOURCE_TYPE == %d \n", PowerSourceType
);
457 return STATUS_UNSUCCESSFUL
;
460 /* Return whatever the FDO creation routine did */