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
;
189 ULONG ReturnedLength
;
191 Irp
->IoStatus
.Information
= 0;
193 DPRINT("Received IOCTL %x for 0x%x\n", IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
,
196 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
)
198 case IOCTL_BATTERY_QUERY_TAG
:
199 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(ULONG
) ||
200 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(ULONG
))
202 Status
= STATUS_BUFFER_TOO_SMALL
;
206 WaitTime
= *(PULONG
)Irp
->AssociatedIrp
.SystemBuffer
;
208 Timeout
.QuadPart
= Int32x32To64(WaitTime
, -1000);
210 Status
= BattClass
->MiniportInfo
.QueryTag(BattClass
->MiniportInfo
.Context
,
211 (PULONG
)Irp
->AssociatedIrp
.SystemBuffer
);
212 if (!NT_SUCCESS(Status
))
214 ExAcquireFastMutex(&BattClass
->Mutex
);
215 BattClass
->EventTrigger
= EVENT_BATTERY_TAG
;
216 BattClass
->Waiting
= TRUE
;
217 ExReleaseFastMutex(&BattClass
->Mutex
);
219 Status
= KeWaitForSingleObject(&BattClass
->WaitEvent
,
223 WaitTime
!= -1 ? &Timeout
: NULL
);
225 ExAcquireFastMutex(&BattClass
->Mutex
);
226 BattClass
->Waiting
= FALSE
;
227 ExReleaseFastMutex(&BattClass
->Mutex
);
229 if (Status
== STATUS_SUCCESS
)
231 Status
= BattClass
->MiniportInfo
.QueryTag(BattClass
->MiniportInfo
.Context
,
232 (PULONG
)Irp
->AssociatedIrp
.SystemBuffer
);
233 if (NT_SUCCESS(Status
))
234 Irp
->IoStatus
.Information
= sizeof(ULONG
);
238 Status
= STATUS_NO_SUCH_DEVICE
;
242 Irp
->IoStatus
.Information
= sizeof(ULONG
);
245 case IOCTL_BATTERY_QUERY_STATUS
:
246 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(*BattWait
) ||
247 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(BATTERY_STATUS
))
249 Status
= STATUS_BUFFER_TOO_SMALL
;
253 BattWait
= Irp
->AssociatedIrp
.SystemBuffer
;
255 Timeout
.QuadPart
= Int32x32To64(BattWait
->Timeout
, -1000);
257 Status
= BattClass
->MiniportInfo
.QueryStatus(BattClass
->MiniportInfo
.Context
,
258 BattWait
->BatteryTag
,
259 (PBATTERY_STATUS
)Irp
->AssociatedIrp
.SystemBuffer
);
261 BattStatus
= Irp
->AssociatedIrp
.SystemBuffer
;
263 if (!NT_SUCCESS(Status
) ||
264 ((BattWait
->PowerState
& BattStatus
->PowerState
) &&
265 (BattWait
->HighCapacity
<= BattStatus
->Capacity
) &&
266 (BattWait
->LowCapacity
>= BattStatus
->Capacity
)))
268 BattNotify
.PowerState
= BattWait
->PowerState
;
269 BattNotify
.HighCapacity
= BattWait
->HighCapacity
;
270 BattNotify
.LowCapacity
= BattWait
->LowCapacity
;
272 BattClass
->MiniportInfo
.SetStatusNotify(BattClass
->MiniportInfo
.Context
,
273 BattWait
->BatteryTag
,
276 ExAcquireFastMutex(&BattClass
->Mutex
);
277 BattClass
->EventTrigger
= EVENT_BATTERY_STATUS
;
278 BattClass
->EventTriggerContext
= BattWait
;
279 BattClass
->Waiting
= TRUE
;
280 ExReleaseFastMutex(&BattClass
->Mutex
);
282 Status
= KeWaitForSingleObject(&BattClass
->WaitEvent
,
286 BattWait
->Timeout
!= -1 ? &Timeout
: NULL
);
288 ExAcquireFastMutex(&BattClass
->Mutex
);
289 BattClass
->Waiting
= FALSE
;
290 ExReleaseFastMutex(&BattClass
->Mutex
);
292 BattClass
->MiniportInfo
.DisableStatusNotify(BattClass
->MiniportInfo
.Context
);
294 if (Status
== STATUS_SUCCESS
)
296 Status
= BattClass
->MiniportInfo
.QueryStatus(BattClass
->MiniportInfo
.Context
,
297 BattWait
->BatteryTag
,
298 (PBATTERY_STATUS
)Irp
->AssociatedIrp
.SystemBuffer
);
299 if (NT_SUCCESS(Status
))
300 Irp
->IoStatus
.Information
= sizeof(ULONG
);
304 Status
= STATUS_NO_SUCH_DEVICE
;
308 Irp
->IoStatus
.Information
= sizeof(BATTERY_STATUS
);
311 case IOCTL_BATTERY_QUERY_INFORMATION
:
312 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(*BattQueryInfo
))
314 Status
= STATUS_BUFFER_TOO_SMALL
;
318 BattQueryInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
320 Status
= BattClass
->MiniportInfo
.QueryInformation(BattClass
->MiniportInfo
.Context
,
321 BattQueryInfo
->BatteryTag
,
322 BattQueryInfo
->InformationLevel
,
323 BattQueryInfo
->AtRate
,
324 Irp
->AssociatedIrp
.SystemBuffer
,
325 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
,
327 Irp
->IoStatus
.Information
= ReturnedLength
;
328 if (!NT_SUCCESS(Status
))
329 DPRINT1("QueryInformation failed (0x%x)\n", Status
);
331 case IOCTL_BATTERY_SET_INFORMATION
:
332 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(*BattSetInfo
))
334 Status
= STATUS_BUFFER_TOO_SMALL
;
338 BattSetInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
340 Status
= BattClass
->MiniportInfo
.SetInformation(BattClass
->MiniportInfo
.Context
,
341 BattSetInfo
->BatteryTag
,
342 BattSetInfo
->InformationLevel
,
343 BattSetInfo
->Buffer
);
344 if (!NT_SUCCESS(Status
))
345 DPRINT1("SetInformation failed (0x%x)\n", Status
);
349 DPRINT1("Received unsupported IRP %x\n", IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
);
350 /* Do NOT complete the irp */
351 return STATUS_NOT_SUPPORTED
;
354 Irp
->IoStatus
.Status
= Status
;
355 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);