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 if (MiniportInfo
->Pdo
!= NULL
)
156 Status
= IoRegisterDeviceInterface(MiniportInfo
->Pdo
,
157 &GUID_DEVICE_BATTERY
,
159 &BattClass
->InterfaceName
);
160 if (NT_SUCCESS(Status
))
162 DPRINT("Initialized battery interface: %wZ\n", &BattClass
->InterfaceName
);
163 Status
= IoSetDeviceInterfaceState(&BattClass
->InterfaceName
, TRUE
);
164 if (Status
== STATUS_OBJECT_NAME_EXISTS
)
166 DPRINT1("Got STATUS_OBJECT_NAME_EXISTS for SetDeviceInterfaceState\n");
167 Status
= STATUS_SUCCESS
;
172 DPRINT1("IoRegisterDeviceInterface failed (0x%x)\n", Status
);
176 *ClassData
= BattClass
;
178 return STATUS_SUCCESS
;
184 BatteryClassIoctl(PVOID ClassData
,
187 PBATTERY_CLASS_DATA BattClass
= ClassData
;
188 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
191 PBATTERY_WAIT_STATUS BattWait
;
192 PBATTERY_QUERY_INFORMATION BattQueryInfo
;
193 PBATTERY_SET_INFORMATION BattSetInfo
;
194 LARGE_INTEGER Timeout
;
195 PBATTERY_STATUS BattStatus
;
196 BATTERY_NOTIFY BattNotify
;
197 ULONG ReturnedLength
;
199 Irp
->IoStatus
.Information
= 0;
201 DPRINT("Received IOCTL %x for 0x%x\n", IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
,
204 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
)
206 case IOCTL_BATTERY_QUERY_TAG
:
207 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(ULONG
) ||
208 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(ULONG
))
210 Status
= STATUS_BUFFER_TOO_SMALL
;
214 WaitTime
= *(PULONG
)Irp
->AssociatedIrp
.SystemBuffer
;
216 Timeout
.QuadPart
= Int32x32To64(WaitTime
, -1000);
218 Status
= BattClass
->MiniportInfo
.QueryTag(BattClass
->MiniportInfo
.Context
,
219 (PULONG
)Irp
->AssociatedIrp
.SystemBuffer
);
220 if (!NT_SUCCESS(Status
))
222 ExAcquireFastMutex(&BattClass
->Mutex
);
223 BattClass
->EventTrigger
= EVENT_BATTERY_TAG
;
224 BattClass
->Waiting
= TRUE
;
225 ExReleaseFastMutex(&BattClass
->Mutex
);
227 Status
= KeWaitForSingleObject(&BattClass
->WaitEvent
,
231 WaitTime
!= -1 ? &Timeout
: NULL
);
233 ExAcquireFastMutex(&BattClass
->Mutex
);
234 BattClass
->Waiting
= FALSE
;
235 ExReleaseFastMutex(&BattClass
->Mutex
);
237 if (Status
== STATUS_SUCCESS
)
239 Status
= BattClass
->MiniportInfo
.QueryTag(BattClass
->MiniportInfo
.Context
,
240 (PULONG
)Irp
->AssociatedIrp
.SystemBuffer
);
241 if (NT_SUCCESS(Status
))
242 Irp
->IoStatus
.Information
= sizeof(ULONG
);
246 Status
= STATUS_NO_SUCH_DEVICE
;
250 Irp
->IoStatus
.Information
= sizeof(ULONG
);
253 case IOCTL_BATTERY_QUERY_STATUS
:
254 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(*BattWait
) ||
255 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(BATTERY_STATUS
))
257 Status
= STATUS_BUFFER_TOO_SMALL
;
261 BattWait
= Irp
->AssociatedIrp
.SystemBuffer
;
263 Timeout
.QuadPart
= Int32x32To64(BattWait
->Timeout
, -1000);
265 Status
= BattClass
->MiniportInfo
.QueryStatus(BattClass
->MiniportInfo
.Context
,
266 BattWait
->BatteryTag
,
267 (PBATTERY_STATUS
)Irp
->AssociatedIrp
.SystemBuffer
);
269 BattStatus
= Irp
->AssociatedIrp
.SystemBuffer
;
271 if (!NT_SUCCESS(Status
) ||
272 ((BattWait
->PowerState
& BattStatus
->PowerState
) &&
273 (BattWait
->HighCapacity
<= BattStatus
->Capacity
) &&
274 (BattWait
->LowCapacity
>= BattStatus
->Capacity
)))
276 BattNotify
.PowerState
= BattWait
->PowerState
;
277 BattNotify
.HighCapacity
= BattWait
->HighCapacity
;
278 BattNotify
.LowCapacity
= BattWait
->LowCapacity
;
280 BattClass
->MiniportInfo
.SetStatusNotify(BattClass
->MiniportInfo
.Context
,
281 BattWait
->BatteryTag
,
284 ExAcquireFastMutex(&BattClass
->Mutex
);
285 BattClass
->EventTrigger
= EVENT_BATTERY_STATUS
;
286 BattClass
->EventTriggerContext
= BattWait
;
287 BattClass
->Waiting
= TRUE
;
288 ExReleaseFastMutex(&BattClass
->Mutex
);
290 Status
= KeWaitForSingleObject(&BattClass
->WaitEvent
,
294 BattWait
->Timeout
!= -1 ? &Timeout
: NULL
);
296 ExAcquireFastMutex(&BattClass
->Mutex
);
297 BattClass
->Waiting
= FALSE
;
298 ExReleaseFastMutex(&BattClass
->Mutex
);
300 BattClass
->MiniportInfo
.DisableStatusNotify(BattClass
->MiniportInfo
.Context
);
302 if (Status
== STATUS_SUCCESS
)
304 Status
= BattClass
->MiniportInfo
.QueryStatus(BattClass
->MiniportInfo
.Context
,
305 BattWait
->BatteryTag
,
306 (PBATTERY_STATUS
)Irp
->AssociatedIrp
.SystemBuffer
);
307 if (NT_SUCCESS(Status
))
308 Irp
->IoStatus
.Information
= sizeof(ULONG
);
312 Status
= STATUS_NO_SUCH_DEVICE
;
316 Irp
->IoStatus
.Information
= sizeof(BATTERY_STATUS
);
319 case IOCTL_BATTERY_QUERY_INFORMATION
:
320 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(*BattQueryInfo
))
322 Status
= STATUS_BUFFER_TOO_SMALL
;
326 BattQueryInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
328 Status
= BattClass
->MiniportInfo
.QueryInformation(BattClass
->MiniportInfo
.Context
,
329 BattQueryInfo
->BatteryTag
,
330 BattQueryInfo
->InformationLevel
,
331 BattQueryInfo
->AtRate
,
332 Irp
->AssociatedIrp
.SystemBuffer
,
333 IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
,
335 Irp
->IoStatus
.Information
= ReturnedLength
;
336 if (!NT_SUCCESS(Status
))
337 DPRINT1("QueryInformation failed (0x%x)\n", Status
);
339 case IOCTL_BATTERY_SET_INFORMATION
:
340 if (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(*BattSetInfo
))
342 Status
= STATUS_BUFFER_TOO_SMALL
;
346 BattSetInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
348 Status
= BattClass
->MiniportInfo
.SetInformation(BattClass
->MiniportInfo
.Context
,
349 BattSetInfo
->BatteryTag
,
350 BattSetInfo
->InformationLevel
,
351 BattSetInfo
->Buffer
);
352 if (!NT_SUCCESS(Status
))
353 DPRINT1("SetInformation failed (0x%x)\n", Status
);
357 DPRINT1("Received unsupported IRP %x\n", IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
);
358 /* Do NOT complete the irp */
359 return STATUS_NOT_SUPPORTED
;
362 Irp
->IoStatus
.Status
= Status
;
363 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);