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
= ClassData
;
31 DPRINT("Battery 0x%x is being unloaded\n");
33 if (BattClass
->InterfaceName
.Length
!= 0)
35 IoSetDeviceInterfaceState(&BattClass
->InterfaceName
, FALSE
);
36 RtlFreeUnicodeString(&BattClass
->InterfaceName
);
39 ExFreePoolWithTag(BattClass
,
40 BATTERY_CLASS_DATA_TAG
);
42 return STATUS_SUCCESS
;
48 BatteryClassSystemControl(PVOID ClassData
,
50 PDEVICE_OBJECT DeviceObject
,
56 return STATUS_WMI_GUID_NOT_FOUND
;
62 BatteryClassQueryWmiDataBlock(PVOID ClassData
,
63 PDEVICE_OBJECT DeviceObject
,
66 PULONG InstanceLengthArray
,
72 return STATUS_WMI_GUID_NOT_FOUND
;
78 BatteryClassStatusNotify(PVOID ClassData
)
80 PBATTERY_CLASS_DATA BattClass
= ClassData
;
81 PBATTERY_WAIT_STATUS BattWait
= BattClass
->EventTriggerContext
;
82 BATTERY_STATUS BattStatus
;
85 DPRINT("Received battery status notification from 0x%x\n", ClassData
);
87 ExAcquireFastMutex(&BattClass
->Mutex
);
88 if (!BattClass
->Waiting
)
90 ExReleaseFastMutex(&BattClass
->Mutex
);
91 return STATUS_SUCCESS
;
94 switch (BattClass
->EventTrigger
)
96 case EVENT_BATTERY_TAG
:
97 ExReleaseFastMutex(&BattClass
->Mutex
);
98 DPRINT1("Waiting for battery is UNIMPLEMENTED!\n");
101 case EVENT_BATTERY_STATUS
:
102 ExReleaseFastMutex(&BattClass
->Mutex
);
103 Status
= BattClass
->MiniportInfo
.QueryStatus(BattClass
->MiniportInfo
.Context
,
104 BattWait
->BatteryTag
,
106 if (!NT_SUCCESS(Status
))
109 ExAcquireFastMutex(&BattClass
->Mutex
);
111 if (!(BattWait
->PowerState
& BattStatus
.PowerState
) ||
112 (BattWait
->HighCapacity
> BattStatus
.Capacity
) ||
113 (BattWait
->LowCapacity
< BattStatus
.Capacity
))
115 KeSetEvent(&BattClass
->WaitEvent
, IO_NO_INCREMENT
, FALSE
);
118 ExReleaseFastMutex(&BattClass
->Mutex
);
122 ExReleaseFastMutex(&BattClass
->Mutex
);
127 return STATUS_SUCCESS
;
133 BatteryClassInitializeDevice(PBATTERY_MINIPORT_INFO MiniportInfo
,
137 PBATTERY_CLASS_DATA BattClass
= ExAllocatePoolWithTag(NonPagedPool
,
138 sizeof(BATTERY_CLASS_DATA
),
139 BATTERY_CLASS_DATA_TAG
);
142 return STATUS_INSUFFICIENT_RESOURCES
;
144 RtlZeroMemory(BattClass
, sizeof(BATTERY_CLASS_DATA
));
146 RtlCopyMemory(&BattClass
->MiniportInfo
,
148 sizeof(BattClass
->MiniportInfo
));
150 KeInitializeEvent(&BattClass
->WaitEvent
, SynchronizationEvent
, FALSE
);
152 ExInitializeFastMutex(&BattClass
->Mutex
);
154 Status
= IoRegisterDeviceInterface(MiniportInfo
->Pdo
,
155 &GUID_DEVICE_BATTERY
,
157 &BattClass
->InterfaceName
);
158 if (NT_SUCCESS(Status
))
160 DPRINT("Initialized battery interface: %wZ\n", &BattClass
->InterfaceName
);
161 IoSetDeviceInterfaceState(&BattClass
->InterfaceName
, TRUE
);
165 DPRINT1("IoRegisterDeviceInterface failed (0x%x)\n", Status
);
168 *ClassData
= BattClass
;
170 return STATUS_SUCCESS
;
176 BatteryClassIoctl(PVOID ClassData
,
179 PBATTERY_CLASS_DATA BattClass
= ClassData
;
180 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
183 PBATTERY_WAIT_STATUS BattWait
;
184 PBATTERY_QUERY_INFORMATION BattQueryInfo
;
185 PBATTERY_SET_INFORMATION BattSetInfo
;
186 LARGE_INTEGER Timeout
;
187 PBATTERY_STATUS BattStatus
;
188 BATTERY_NOTIFY BattNotify
;
190 Irp
->IoStatus
.Information
= 0;
192 DPRINT("Received IOCTL %x for 0x%x\n", IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
,
195 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
)
197 case IOCTL_BATTERY_QUERY_TAG
:
198 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(ULONG
) ||
199 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(ULONG
))
201 Status
= STATUS_BUFFER_TOO_SMALL
;
205 WaitTime
= *(PULONG
)Irp
->AssociatedIrp
.SystemBuffer
;
207 Timeout
.QuadPart
= Int32x32To64(WaitTime
, -1000);
209 Status
= BattClass
->MiniportInfo
.QueryTag(BattClass
->MiniportInfo
.Context
,
210 (PULONG
)Irp
->AssociatedIrp
.SystemBuffer
);
211 if (!NT_SUCCESS(Status
))
213 ExAcquireFastMutex(&BattClass
->Mutex
);
214 BattClass
->EventTrigger
= EVENT_BATTERY_TAG
;
215 BattClass
->Waiting
= TRUE
;
216 ExReleaseFastMutex(&BattClass
->Mutex
);
218 Status
= KeWaitForSingleObject(&BattClass
->WaitEvent
,
222 WaitTime
!= -1 ? &Timeout
: NULL
);
224 ExAcquireFastMutex(&BattClass
->Mutex
);
225 BattClass
->Waiting
= FALSE
;
226 ExReleaseFastMutex(&BattClass
->Mutex
);
228 if (Status
== STATUS_SUCCESS
)
230 Status
= BattClass
->MiniportInfo
.QueryTag(BattClass
->MiniportInfo
.Context
,
231 (PULONG
)Irp
->AssociatedIrp
.SystemBuffer
);
232 if (NT_SUCCESS(Status
))
233 Irp
->IoStatus
.Information
= sizeof(ULONG
);
237 Status
= STATUS_NO_SUCH_DEVICE
;
241 Irp
->IoStatus
.Information
= sizeof(ULONG
);
244 case IOCTL_BATTERY_QUERY_STATUS
:
245 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(*BattWait
) ||
246 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(BATTERY_STATUS
))
248 Status
= STATUS_BUFFER_TOO_SMALL
;
252 BattWait
= Irp
->AssociatedIrp
.SystemBuffer
;
254 Timeout
.QuadPart
= Int32x32To64(BattWait
->Timeout
, -1000);
256 Status
= BattClass
->MiniportInfo
.QueryStatus(BattClass
->MiniportInfo
.Context
,
257 BattWait
->BatteryTag
,
258 (PBATTERY_STATUS
)Irp
->AssociatedIrp
.SystemBuffer
);
260 BattStatus
= Irp
->AssociatedIrp
.SystemBuffer
;
262 if (!NT_SUCCESS(Status
) ||
263 ((BattWait
->PowerState
& BattStatus
->PowerState
) &&
264 (BattWait
->HighCapacity
<= BattStatus
->Capacity
) &&
265 (BattWait
->LowCapacity
>= BattStatus
->Capacity
)))
267 BattNotify
.PowerState
= BattWait
->PowerState
;
268 BattNotify
.HighCapacity
= BattWait
->HighCapacity
;
269 BattNotify
.LowCapacity
= BattWait
->LowCapacity
;
271 BattClass
->MiniportInfo
.SetStatusNotify(BattClass
->MiniportInfo
.Context
,
272 BattWait
->BatteryTag
,
275 ExAcquireFastMutex(&BattClass
->Mutex
);
276 BattClass
->EventTrigger
= EVENT_BATTERY_STATUS
;
277 BattClass
->EventTriggerContext
= BattWait
;
278 BattClass
->Waiting
= TRUE
;
279 ExReleaseFastMutex(&BattClass
->Mutex
);
281 Status
= KeWaitForSingleObject(&BattClass
->WaitEvent
,
285 BattWait
->Timeout
!= -1 ? &Timeout
: NULL
);
287 ExAcquireFastMutex(&BattClass
->Mutex
);
288 BattClass
->Waiting
= FALSE
;
289 ExReleaseFastMutex(&BattClass
->Mutex
);
291 BattClass
->MiniportInfo
.DisableStatusNotify(BattClass
->MiniportInfo
.Context
);
293 if (Status
== STATUS_SUCCESS
)
295 Status
= BattClass
->MiniportInfo
.QueryStatus(BattClass
->MiniportInfo
.Context
,
296 BattWait
->BatteryTag
,
297 (PBATTERY_STATUS
)Irp
->AssociatedIrp
.SystemBuffer
);
298 if (NT_SUCCESS(Status
))
299 Irp
->IoStatus
.Information
= sizeof(ULONG
);
303 Status
= STATUS_NO_SUCH_DEVICE
;
307 Irp
->IoStatus
.Information
= sizeof(BATTERY_STATUS
);
310 case IOCTL_BATTERY_QUERY_INFORMATION
:
311 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(*BattQueryInfo
))
313 Status
= STATUS_BUFFER_TOO_SMALL
;
317 BattQueryInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
319 Status
= BattClass
->MiniportInfo
.QueryInformation(BattClass
->MiniportInfo
.Context
,
320 BattQueryInfo
->BatteryTag
,
321 BattQueryInfo
->InformationLevel
,
322 BattQueryInfo
->AtRate
,
323 Irp
->AssociatedIrp
.SystemBuffer
,
324 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
,
325 &Irp
->IoStatus
.Information
);
326 if (!NT_SUCCESS(Status
))
327 DPRINT1("QueryInformation failed (0x%x)\n", Status
);
329 case IOCTL_BATTERY_SET_INFORMATION
:
330 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(*BattSetInfo
))
332 Status
= STATUS_BUFFER_TOO_SMALL
;
336 BattSetInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
338 Status
= BattClass
->MiniportInfo
.SetInformation(BattClass
->MiniportInfo
.Context
,
339 BattSetInfo
->BatteryTag
,
340 BattSetInfo
->InformationLevel
,
341 BattSetInfo
->Buffer
);
342 if (!NT_SUCCESS(Status
))
343 DPRINT1("SetInformation failed (0x%x)\n", Status
);
347 DPRINT1("Received unsupported IRP %x\n", IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
);
348 /* Do NOT complete the irp */
349 return STATUS_NOT_SUPPORTED
;
352 Irp
->IoStatus
.Status
= Status
;
353 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);