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
,
58 /* FIXME: Uncomment when WmiCompleteRequest is implemented */
60 Status
= STATUS_WMI_GUID_NOT_FOUND
;
61 WmiCompleteRequest(DeviceObject
,
67 Irp
->IoStatus
.Status
= Status
= STATUS_WMI_GUID_NOT_FOUND
;
68 Irp
->IoStatus
.Information
= 0;
70 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
79 BatteryClassQueryWmiDataBlock(PVOID ClassData
,
80 PDEVICE_OBJECT DeviceObject
,
83 PULONG InstanceLengthArray
,
89 return STATUS_WMI_GUID_NOT_FOUND
;
95 BatteryClassStatusNotify(PVOID ClassData
)
97 PBATTERY_CLASS_DATA BattClass
= ClassData
;
98 PBATTERY_WAIT_STATUS BattWait
= BattClass
->EventTriggerContext
;
99 BATTERY_STATUS BattStatus
;
102 DPRINT("Received battery status notification from 0x%x\n", ClassData
);
104 ExAcquireFastMutex(&BattClass
->Mutex
);
105 if (!BattClass
->Waiting
)
107 ExReleaseFastMutex(&BattClass
->Mutex
);
108 return STATUS_SUCCESS
;
111 switch (BattClass
->EventTrigger
)
113 case EVENT_BATTERY_TAG
:
114 ExReleaseFastMutex(&BattClass
->Mutex
);
115 DPRINT1("Waiting for battery is UNIMPLEMENTED!\n");
118 case EVENT_BATTERY_STATUS
:
119 ExReleaseFastMutex(&BattClass
->Mutex
);
120 Status
= BattClass
->MiniportInfo
.QueryStatus(BattClass
->MiniportInfo
.Context
,
121 BattWait
->BatteryTag
,
123 if (!NT_SUCCESS(Status
))
126 ExAcquireFastMutex(&BattClass
->Mutex
);
128 if (!(BattWait
->PowerState
& BattStatus
.PowerState
) ||
129 (BattWait
->HighCapacity
> BattStatus
.Capacity
) ||
130 (BattWait
->LowCapacity
< BattStatus
.Capacity
))
132 KeSetEvent(&BattClass
->WaitEvent
, IO_NO_INCREMENT
, FALSE
);
135 ExReleaseFastMutex(&BattClass
->Mutex
);
139 ExReleaseFastMutex(&BattClass
->Mutex
);
144 return STATUS_SUCCESS
;
150 BatteryClassInitializeDevice(PBATTERY_MINIPORT_INFO MiniportInfo
,
154 PBATTERY_CLASS_DATA BattClass
= ExAllocatePoolWithTag(NonPagedPool
,
155 sizeof(BATTERY_CLASS_DATA
),
156 BATTERY_CLASS_DATA_TAG
);
159 return STATUS_INSUFFICIENT_RESOURCES
;
161 RtlZeroMemory(BattClass
, sizeof(BATTERY_CLASS_DATA
));
163 RtlCopyMemory(&BattClass
->MiniportInfo
,
165 sizeof(BattClass
->MiniportInfo
));
167 KeInitializeEvent(&BattClass
->WaitEvent
, SynchronizationEvent
, FALSE
);
169 ExInitializeFastMutex(&BattClass
->Mutex
);
171 Status
= IoRegisterDeviceInterface(MiniportInfo
->Pdo
,
172 &GUID_DEVICE_BATTERY
,
174 &BattClass
->InterfaceName
);
175 if (NT_SUCCESS(Status
))
177 DPRINT("Initialized battery interface: %wZ\n", &BattClass
->InterfaceName
);
178 IoSetDeviceInterfaceState(&BattClass
->InterfaceName
, TRUE
);
182 DPRINT1("IoRegisterDeviceInterface failed (0x%x)\n", Status
);
185 *ClassData
= BattClass
;
187 return STATUS_SUCCESS
;
193 BatteryClassIoctl(PVOID ClassData
,
196 PBATTERY_CLASS_DATA BattClass
= ClassData
;
197 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
200 PBATTERY_WAIT_STATUS BattWait
;
201 PBATTERY_QUERY_INFORMATION BattQueryInfo
;
202 PBATTERY_SET_INFORMATION BattSetInfo
;
203 LARGE_INTEGER Timeout
;
204 PBATTERY_STATUS BattStatus
;
205 BATTERY_NOTIFY BattNotify
;
207 Irp
->IoStatus
.Information
= 0;
209 DPRINT("Received IOCTL %x for 0x%x\n", IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
,
212 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
)
214 case IOCTL_BATTERY_QUERY_TAG
:
215 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(ULONG
) ||
216 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(ULONG
))
218 Status
= STATUS_BUFFER_TOO_SMALL
;
222 WaitTime
= *(PULONG
)Irp
->AssociatedIrp
.SystemBuffer
;
224 Timeout
.QuadPart
= Int32x32To64(WaitTime
, -1000);
226 Status
= BattClass
->MiniportInfo
.QueryTag(BattClass
->MiniportInfo
.Context
,
227 (PULONG
)Irp
->AssociatedIrp
.SystemBuffer
);
228 if (!NT_SUCCESS(Status
))
230 ExAcquireFastMutex(&BattClass
->Mutex
);
231 BattClass
->EventTrigger
= EVENT_BATTERY_TAG
;
232 BattClass
->Waiting
= TRUE
;
233 ExReleaseFastMutex(&BattClass
->Mutex
);
235 Status
= KeWaitForSingleObject(&BattClass
->WaitEvent
,
239 WaitTime
!= -1 ? &Timeout
: NULL
);
241 ExAcquireFastMutex(&BattClass
->Mutex
);
242 BattClass
->Waiting
= FALSE
;
243 ExReleaseFastMutex(&BattClass
->Mutex
);
245 if (Status
== STATUS_SUCCESS
)
247 Status
= BattClass
->MiniportInfo
.QueryTag(BattClass
->MiniportInfo
.Context
,
248 (PULONG
)Irp
->AssociatedIrp
.SystemBuffer
);
249 if (NT_SUCCESS(Status
))
250 Irp
->IoStatus
.Information
= sizeof(ULONG
);
254 Status
= STATUS_NO_SUCH_DEVICE
;
258 Irp
->IoStatus
.Information
= sizeof(ULONG
);
261 case IOCTL_BATTERY_QUERY_STATUS
:
262 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(*BattWait
) ||
263 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(BATTERY_STATUS
))
265 Status
= STATUS_BUFFER_TOO_SMALL
;
269 BattWait
= Irp
->AssociatedIrp
.SystemBuffer
;
271 Timeout
.QuadPart
= Int32x32To64(BattWait
->Timeout
, -1000);
273 Status
= BattClass
->MiniportInfo
.QueryStatus(BattClass
->MiniportInfo
.Context
,
274 BattWait
->BatteryTag
,
275 (PBATTERY_STATUS
)Irp
->AssociatedIrp
.SystemBuffer
);
277 BattStatus
= Irp
->AssociatedIrp
.SystemBuffer
;
279 if (!NT_SUCCESS(Status
) ||
280 ((BattWait
->PowerState
& BattStatus
->PowerState
) &&
281 (BattWait
->HighCapacity
<= BattStatus
->Capacity
) &&
282 (BattWait
->LowCapacity
>= BattStatus
->Capacity
)))
284 BattNotify
.PowerState
= BattWait
->PowerState
;
285 BattNotify
.HighCapacity
= BattWait
->HighCapacity
;
286 BattNotify
.LowCapacity
= BattWait
->LowCapacity
;
288 BattClass
->MiniportInfo
.SetStatusNotify(BattClass
->MiniportInfo
.Context
,
289 BattWait
->BatteryTag
,
292 ExAcquireFastMutex(&BattClass
->Mutex
);
293 BattClass
->EventTrigger
= EVENT_BATTERY_STATUS
;
294 BattClass
->EventTriggerContext
= BattWait
;
295 BattClass
->Waiting
= TRUE
;
296 ExReleaseFastMutex(&BattClass
->Mutex
);
298 Status
= KeWaitForSingleObject(&BattClass
->WaitEvent
,
302 BattWait
->Timeout
!= -1 ? &Timeout
: NULL
);
304 ExAcquireFastMutex(&BattClass
->Mutex
);
305 BattClass
->Waiting
= FALSE
;
306 ExReleaseFastMutex(&BattClass
->Mutex
);
308 BattClass
->MiniportInfo
.DisableStatusNotify(BattClass
->MiniportInfo
.Context
);
310 if (Status
== STATUS_SUCCESS
)
312 Status
= BattClass
->MiniportInfo
.QueryStatus(BattClass
->MiniportInfo
.Context
,
313 BattWait
->BatteryTag
,
314 (PBATTERY_STATUS
)Irp
->AssociatedIrp
.SystemBuffer
);
315 if (NT_SUCCESS(Status
))
316 Irp
->IoStatus
.Information
= sizeof(ULONG
);
320 Status
= STATUS_NO_SUCH_DEVICE
;
324 Irp
->IoStatus
.Information
= sizeof(BATTERY_STATUS
);
327 case IOCTL_BATTERY_QUERY_INFORMATION
:
328 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(*BattQueryInfo
))
330 Status
= STATUS_BUFFER_TOO_SMALL
;
334 BattQueryInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
336 Status
= BattClass
->MiniportInfo
.QueryInformation(BattClass
->MiniportInfo
.Context
,
337 BattQueryInfo
->BatteryTag
,
338 BattQueryInfo
->InformationLevel
,
339 BattQueryInfo
->AtRate
,
340 Irp
->AssociatedIrp
.SystemBuffer
,
341 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
,
342 &Irp
->IoStatus
.Information
);
343 if (!NT_SUCCESS(Status
))
344 DPRINT1("QueryInformation failed (0x%x)\n", Status
);
346 case IOCTL_BATTERY_SET_INFORMATION
:
347 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(*BattSetInfo
))
349 Status
= STATUS_BUFFER_TOO_SMALL
;
353 BattSetInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
355 Status
= BattClass
->MiniportInfo
.SetInformation(BattClass
->MiniportInfo
.Context
,
356 BattSetInfo
->BatteryTag
,
357 BattSetInfo
->InformationLevel
,
358 BattSetInfo
->Buffer
);
359 if (!NT_SUCCESS(Status
))
360 DPRINT1("SetInformation failed (0x%x)\n", Status
);
364 DPRINT1("Received unsupported IRP %x\n", IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
);
365 /* Do NOT complete the irp */
366 return STATUS_NOT_SUPPORTED
;
369 Irp
->IoStatus
.Status
= Status
;
370 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);