2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/battery/battc/battc.c
5 * PURPOSE: Battery Class Driver
6 * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
16 DriverEntry(PDRIVER_OBJECT DriverObject
,
17 PUNICODE_STRING RegistryPath
)
19 DPRINT("Battery class driver initialized\n");
21 return STATUS_SUCCESS
;
27 BatteryClassUnload(PVOID ClassData
)
29 PBATTERY_CLASS_DATA BattClass
;
31 DPRINT("Battery %p is being unloaded\n", ClassData
);
33 BattClass
= ClassData
;
34 if (BattClass
->InterfaceName
.Length
!= 0)
36 IoSetDeviceInterfaceState(&BattClass
->InterfaceName
, FALSE
);
37 RtlFreeUnicodeString(&BattClass
->InterfaceName
);
40 ExFreePoolWithTag(BattClass
,
41 BATTERY_CLASS_DATA_TAG
);
43 return STATUS_SUCCESS
;
49 BatteryClassSystemControl(PVOID ClassData
,
51 PDEVICE_OBJECT DeviceObject
,
57 return STATUS_WMI_GUID_NOT_FOUND
;
63 BatteryClassQueryWmiDataBlock(PVOID ClassData
,
64 PDEVICE_OBJECT DeviceObject
,
67 PULONG InstanceLengthArray
,
73 return STATUS_WMI_GUID_NOT_FOUND
;
79 BatteryClassStatusNotify(PVOID ClassData
)
81 PBATTERY_CLASS_DATA BattClass
;
82 PBATTERY_WAIT_STATUS BattWait
;
83 BATTERY_STATUS BattStatus
;
86 DPRINT("Received battery status notification from %p\n", ClassData
);
88 BattClass
= ClassData
;
89 BattWait
= BattClass
->EventTriggerContext
;
91 ExAcquireFastMutex(&BattClass
->Mutex
);
92 if (!BattClass
->Waiting
)
94 ExReleaseFastMutex(&BattClass
->Mutex
);
95 return STATUS_SUCCESS
;
98 switch (BattClass
->EventTrigger
)
100 case EVENT_BATTERY_TAG
:
101 ExReleaseFastMutex(&BattClass
->Mutex
);
102 DPRINT1("Waiting for battery is UNIMPLEMENTED!\n");
105 case EVENT_BATTERY_STATUS
:
106 ExReleaseFastMutex(&BattClass
->Mutex
);
107 Status
= BattClass
->MiniportInfo
.QueryStatus(BattClass
->MiniportInfo
.Context
,
108 BattWait
->BatteryTag
,
110 if (!NT_SUCCESS(Status
))
113 ExAcquireFastMutex(&BattClass
->Mutex
);
115 if (!(BattWait
->PowerState
& BattStatus
.PowerState
) ||
116 (BattWait
->HighCapacity
> BattStatus
.Capacity
) ||
117 (BattWait
->LowCapacity
< BattStatus
.Capacity
))
119 KeSetEvent(&BattClass
->WaitEvent
, IO_NO_INCREMENT
, FALSE
);
122 ExReleaseFastMutex(&BattClass
->Mutex
);
126 ExReleaseFastMutex(&BattClass
->Mutex
);
131 return STATUS_SUCCESS
;
137 BatteryClassInitializeDevice(PBATTERY_MINIPORT_INFO MiniportInfo
,
141 PBATTERY_CLASS_DATA BattClass
;
143 BattClass
= ExAllocatePoolWithTag(NonPagedPool
,
144 sizeof(BATTERY_CLASS_DATA
),
145 BATTERY_CLASS_DATA_TAG
);
146 if (BattClass
== NULL
)
147 return STATUS_INSUFFICIENT_RESOURCES
;
149 RtlZeroMemory(BattClass
, sizeof(BATTERY_CLASS_DATA
));
151 RtlCopyMemory(&BattClass
->MiniportInfo
,
153 sizeof(BattClass
->MiniportInfo
));
155 KeInitializeEvent(&BattClass
->WaitEvent
, SynchronizationEvent
, FALSE
);
157 ExInitializeFastMutex(&BattClass
->Mutex
);
159 if (MiniportInfo
->Pdo
!= NULL
)
161 Status
= IoRegisterDeviceInterface(MiniportInfo
->Pdo
,
162 &GUID_DEVICE_BATTERY
,
164 &BattClass
->InterfaceName
);
165 if (NT_SUCCESS(Status
))
167 DPRINT("Initialized battery interface: %wZ\n", &BattClass
->InterfaceName
);
168 Status
= IoSetDeviceInterfaceState(&BattClass
->InterfaceName
, TRUE
);
169 if (Status
== STATUS_OBJECT_NAME_EXISTS
)
171 DPRINT1("Got STATUS_OBJECT_NAME_EXISTS for SetDeviceInterfaceState\n");
172 Status
= STATUS_SUCCESS
;
177 DPRINT1("IoRegisterDeviceInterface failed (0x%x)\n", Status
);
181 *ClassData
= BattClass
;
183 return STATUS_SUCCESS
;
189 BatteryClassIoctl(PVOID ClassData
,
192 PBATTERY_CLASS_DATA BattClass
;
193 PIO_STACK_LOCATION IrpSp
;
196 PBATTERY_WAIT_STATUS BattWait
;
197 PBATTERY_QUERY_INFORMATION BattQueryInfo
;
198 PBATTERY_SET_INFORMATION BattSetInfo
;
199 LARGE_INTEGER Timeout
;
200 PBATTERY_STATUS BattStatus
;
201 BATTERY_NOTIFY BattNotify
;
202 ULONG ReturnedLength
;
204 DPRINT("BatteryClassIoctl(%p %p)\n", ClassData
, Irp
);
206 BattClass
= ClassData
;
208 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
209 Irp
->IoStatus
.Information
= 0;
211 DPRINT("Received IOCTL %x for %p\n", IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
,
214 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
)
216 case IOCTL_BATTERY_QUERY_TAG
:
217 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(ULONG
) ||
218 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(ULONG
))
220 Status
= STATUS_BUFFER_TOO_SMALL
;
224 WaitTime
= *(PULONG
)Irp
->AssociatedIrp
.SystemBuffer
;
226 Timeout
.QuadPart
= Int32x32To64(WaitTime
, -1000);
228 Status
= BattClass
->MiniportInfo
.QueryTag(BattClass
->MiniportInfo
.Context
,
229 (PULONG
)Irp
->AssociatedIrp
.SystemBuffer
);
230 if (!NT_SUCCESS(Status
))
232 ExAcquireFastMutex(&BattClass
->Mutex
);
233 BattClass
->EventTrigger
= EVENT_BATTERY_TAG
;
234 BattClass
->Waiting
= TRUE
;
235 ExReleaseFastMutex(&BattClass
->Mutex
);
237 Status
= KeWaitForSingleObject(&BattClass
->WaitEvent
,
241 WaitTime
!= -1 ? &Timeout
: NULL
);
243 ExAcquireFastMutex(&BattClass
->Mutex
);
244 BattClass
->Waiting
= FALSE
;
245 ExReleaseFastMutex(&BattClass
->Mutex
);
247 if (Status
== STATUS_SUCCESS
)
249 Status
= BattClass
->MiniportInfo
.QueryTag(BattClass
->MiniportInfo
.Context
,
250 (PULONG
)Irp
->AssociatedIrp
.SystemBuffer
);
251 if (NT_SUCCESS(Status
))
252 Irp
->IoStatus
.Information
= sizeof(ULONG
);
256 Status
= STATUS_NO_SUCH_DEVICE
;
261 Irp
->IoStatus
.Information
= sizeof(ULONG
);
265 case IOCTL_BATTERY_QUERY_STATUS
:
266 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(*BattWait
) ||
267 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(BATTERY_STATUS
))
269 Status
= STATUS_BUFFER_TOO_SMALL
;
273 BattWait
= Irp
->AssociatedIrp
.SystemBuffer
;
275 Timeout
.QuadPart
= Int32x32To64(BattWait
->Timeout
, -1000);
277 Status
= BattClass
->MiniportInfo
.QueryStatus(BattClass
->MiniportInfo
.Context
,
278 BattWait
->BatteryTag
,
279 (PBATTERY_STATUS
)Irp
->AssociatedIrp
.SystemBuffer
);
281 BattStatus
= Irp
->AssociatedIrp
.SystemBuffer
;
283 if (!NT_SUCCESS(Status
) ||
284 ((BattWait
->PowerState
& BattStatus
->PowerState
) &&
285 (BattWait
->HighCapacity
<= BattStatus
->Capacity
) &&
286 (BattWait
->LowCapacity
>= BattStatus
->Capacity
)))
288 BattNotify
.PowerState
= BattWait
->PowerState
;
289 BattNotify
.HighCapacity
= BattWait
->HighCapacity
;
290 BattNotify
.LowCapacity
= BattWait
->LowCapacity
;
292 BattClass
->MiniportInfo
.SetStatusNotify(BattClass
->MiniportInfo
.Context
,
293 BattWait
->BatteryTag
,
296 ExAcquireFastMutex(&BattClass
->Mutex
);
297 BattClass
->EventTrigger
= EVENT_BATTERY_STATUS
;
298 BattClass
->EventTriggerContext
= BattWait
;
299 BattClass
->Waiting
= TRUE
;
300 ExReleaseFastMutex(&BattClass
->Mutex
);
302 Status
= KeWaitForSingleObject(&BattClass
->WaitEvent
,
306 BattWait
->Timeout
!= -1 ? &Timeout
: NULL
);
308 ExAcquireFastMutex(&BattClass
->Mutex
);
309 BattClass
->Waiting
= FALSE
;
310 ExReleaseFastMutex(&BattClass
->Mutex
);
312 BattClass
->MiniportInfo
.DisableStatusNotify(BattClass
->MiniportInfo
.Context
);
314 if (Status
== STATUS_SUCCESS
)
316 Status
= BattClass
->MiniportInfo
.QueryStatus(BattClass
->MiniportInfo
.Context
,
317 BattWait
->BatteryTag
,
318 (PBATTERY_STATUS
)Irp
->AssociatedIrp
.SystemBuffer
);
319 if (NT_SUCCESS(Status
))
320 Irp
->IoStatus
.Information
= sizeof(ULONG
);
324 Status
= STATUS_NO_SUCH_DEVICE
;
329 Irp
->IoStatus
.Information
= sizeof(BATTERY_STATUS
);
333 case IOCTL_BATTERY_QUERY_INFORMATION
:
334 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(*BattQueryInfo
))
336 Status
= STATUS_BUFFER_TOO_SMALL
;
340 BattQueryInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
342 Status
= BattClass
->MiniportInfo
.QueryInformation(BattClass
->MiniportInfo
.Context
,
343 BattQueryInfo
->BatteryTag
,
344 BattQueryInfo
->InformationLevel
,
345 BattQueryInfo
->AtRate
,
346 Irp
->AssociatedIrp
.SystemBuffer
,
347 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
,
349 Irp
->IoStatus
.Information
= ReturnedLength
;
350 if (!NT_SUCCESS(Status
))
352 DPRINT1("QueryInformation failed (0x%x)\n", Status
);
356 case IOCTL_BATTERY_SET_INFORMATION
:
357 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(*BattSetInfo
))
359 Status
= STATUS_BUFFER_TOO_SMALL
;
363 BattSetInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
365 Status
= BattClass
->MiniportInfo
.SetInformation(BattClass
->MiniportInfo
.Context
,
366 BattSetInfo
->BatteryTag
,
367 BattSetInfo
->InformationLevel
,
368 BattSetInfo
->Buffer
);
369 if (!NT_SUCCESS(Status
))
371 DPRINT1("SetInformation failed (0x%x)\n", Status
);
376 DPRINT1("Received unsupported IRP %x\n", IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
);
377 /* Do NOT complete the irp */
378 return STATUS_NOT_SUPPORTED
;
381 Irp
->IoStatus
.Status
= Status
;
382 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);