b8c59739d4efdf7ef4159ea437d6216c8e3502b6
[reactos.git] / reactos / drivers / bus / acpi / cmbatt / cmbatt.c
1 /*
2 * PROJECT: ReactOS ACPI-Compliant Control Method Battery
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: boot/drivers/bus/acpi/cmbatt/cmbatt.c
5 * PURPOSE: Main Initialization Code and IRP Handling
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "cmbatt.h"
12
13 /* GLOBALS ********************************************************************/
14
15 ULONG CmBattDebug;
16 PCALLBACK_OBJECT CmBattPowerCallBackObject;
17 PVOID CmBattPowerCallBackRegistration;
18 UNICODE_STRING GlobalRegistryPath;
19 KTIMER CmBattWakeDpcTimerObject;
20 KDPC CmBattWakeDpcObject;
21
22 /* FUNCTIONS ******************************************************************/
23
24 VOID
25 NTAPI
26 CmBattPowerCallBack(PCMBATT_DEVICE_EXTENSION DeviceExtension,
27 PVOID Argument1,
28 PVOID Argument2)
29 {
30 UNIMPLEMENTED;
31 }
32
33 VOID
34 NTAPI
35 CmBattWakeDpc(PKDPC Dpc,
36 PCMBATT_DEVICE_EXTENSION FdoExtension,
37 PVOID SystemArgument1,
38 PVOID SystemArgument2)
39 {
40
41 }
42
43 VOID
44 NTAPI
45 CmBattNotifyHandler(PCMBATT_DEVICE_EXTENSION DeviceExtension,
46 ULONG NotifyValue)
47 {
48 UNIMPLEMENTED;
49 }
50
51 VOID
52 NTAPI
53 CmBattUnload(IN PDRIVER_OBJECT DriverObject)
54 {
55 if (CmBattDebug & CMBATT_GENERIC_INFO) DPRINT("CmBattUnload: \n");
56
57 /* Check if we have a registered power callback */
58 if (CmBattPowerCallBackObject)
59 {
60 /* Get rid of it */
61 ExUnregisterCallback(CmBattPowerCallBackRegistration);
62 ObfDereferenceObject(CmBattPowerCallBackObject);
63 }
64
65 /* Free the registry buffer if it exists */
66 if (GlobalRegistryPath.Buffer) ExFreePool(GlobalRegistryPath.Buffer);
67
68 /* Make sure we don't still have references to the DO */
69 if ((DriverObject->DeviceObject) && (CmBattDebug & CMBATT_GENERIC_WARNING))
70 {
71 DbgPrint("Unload called before all devices removed.\n");
72 }
73 }
74
75 NTSTATUS
76 NTAPI
77 CmBattVerifyStaticInfo(ULONG StaData,
78 ULONG BatteryTag)
79 {
80 UNIMPLEMENTED;
81 return STATUS_NOT_IMPLEMENTED;
82 }
83
84 NTSTATUS
85 NTAPI
86 CmBattOpenClose(IN PDEVICE_OBJECT DeviceObject,
87 IN PIRP Irp)
88 {
89 NTSTATUS Status = STATUS_SUCCESS;
90 PIO_STACK_LOCATION IoStackLocation;
91 UCHAR Major;
92 ULONG Count;
93 PCMBATT_DEVICE_EXTENSION DeviceExtension;
94 PAGED_CODE();
95 if (CmBattDebug & CMBATT_GENERIC_INFO) DPRINT("CmBattOpenClose\n");
96
97 /* Grab the device extension and lock it */
98 DeviceExtension = DeviceObject->DeviceExtension;
99 ExAcquireFastMutex(&DeviceExtension->FastMutex);
100
101 /* Check if someone is trying to open a device that doesn't exist yet */
102 Count = DeviceExtension->HandleCount;
103 if (Count == 0xFFFFFFFF)
104 {
105 /* Fail the request */
106 Status = STATUS_NO_SUCH_DEVICE;
107 if (CmBattDebug & CMBATT_PNP_INFO)
108 {
109 DbgPrint("CmBattOpenClose: Failed (UID = %x)(device being removed).\n",
110 DeviceExtension->Tag);
111 }
112 goto Complete;
113 }
114
115 /* Check if this is an open or close */
116 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
117 Major = IoStackLocation->MajorFunction;
118 if (Major == IRP_MJ_CREATE)
119 {
120 /* Increment the open count */
121 DeviceExtension->HandleCount = Count + 1;
122 if (CmBattDebug & CMBATT_PNP_INFO)
123 {
124 DbgPrint("CmBattOpenClose: Open (DeviceNumber = %x)(count = %x).\n",
125 DeviceExtension->DeviceId, Count + 1);
126 }
127 }
128 else if (Major == IRP_MJ_CLOSE)
129 {
130 /* Decrement the open count */
131 DeviceExtension->HandleCount = Count - 1;
132 if (CmBattDebug & CMBATT_PNP_INFO)
133 {
134 DbgPrint("CmBattOpenClose: Close (DeviceNumber = %x)(count = %x).\n",
135 DeviceExtension->DeviceId, Count + 1);
136 }
137 }
138
139 Complete:
140 /* Release lock and complete request */
141 ExReleaseFastMutex(&DeviceExtension->FastMutex);
142 Irp->IoStatus.Status = Status;
143 IofCompleteRequest(Irp, IO_NO_INCREMENT);
144 return Status;
145 }
146
147 NTSTATUS
148 NTAPI
149 CmBattIoctl(PDEVICE_OBJECT DeviceObject,
150 PIRP Irp)
151 {
152 UNIMPLEMENTED;
153 return STATUS_NOT_IMPLEMENTED;
154 }
155
156 NTSTATUS
157 NTAPI
158 CmBattQueryTag(PCMBATT_DEVICE_EXTENSION DeviceExtension,
159 PULONG BatteryTag)
160 {
161 UNIMPLEMENTED;
162 return STATUS_NOT_IMPLEMENTED;
163 }
164
165 NTSTATUS
166 NTAPI
167 CmBattDisableStatusNotify(PCMBATT_DEVICE_EXTENSION DeviceExtension)
168 {
169 UNIMPLEMENTED;
170 return STATUS_NOT_IMPLEMENTED;
171 }
172
173 NTSTATUS
174 NTAPI
175 CmBattSetStatusNotify(PCMBATT_DEVICE_EXTENSION DeviceExtension,
176 ULONG BatteryTag,
177 PBATTERY_NOTIFY BatteryNotify)
178 {
179 UNIMPLEMENTED;
180 return STATUS_NOT_IMPLEMENTED;
181 }
182
183 NTSTATUS
184 NTAPI
185 CmBattGetBatteryStatus(PCMBATT_DEVICE_EXTENSION DeviceExtension,
186 ULONG BatteryTag)
187 {
188 UNIMPLEMENTED;
189 return STATUS_NOT_IMPLEMENTED;
190 }
191
192 NTSTATUS
193 NTAPI
194 CmBattQueryInformation(PCMBATT_DEVICE_EXTENSION DeviceExtension,
195 ULONG BatteryTag,
196 BATTERY_QUERY_INFORMATION_LEVEL Level,
197 OPTIONAL LONG AtRate,
198 PVOID Buffer,
199 ULONG BufferLength,
200 PULONG ReturnedLength)
201 {
202 UNIMPLEMENTED;
203 return STATUS_NOT_IMPLEMENTED;
204 }
205
206 NTSTATUS
207 NTAPI
208 CmBattQueryStatus(PCMBATT_DEVICE_EXTENSION DeviceExtension,
209 ULONG BatteryTag,
210 PBATTERY_STATUS BatteryStatus)
211 {
212 UNIMPLEMENTED;
213 return STATUS_NOT_IMPLEMENTED;
214 }
215
216 NTSTATUS
217 NTAPI
218 DriverEntry(IN PDRIVER_OBJECT DriverObject,
219 IN PUNICODE_STRING RegistryPath)
220 {
221 NTSTATUS Status;
222 PDRIVER_EXTENSION DriverExtension;
223 OBJECT_ATTRIBUTES ObjectAttributes;
224 UNICODE_STRING CallbackName;
225
226 /* Allocate registry path */
227 GlobalRegistryPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL);
228 GlobalRegistryPath.Length = RegistryPath->Length;
229 GlobalRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
230 GlobalRegistryPath.MaximumLength,
231 'MtaB');
232 if (!GlobalRegistryPath.Buffer)
233 {
234 /* Fail if we're out of memory this early */
235 if (CmBattDebug & CMBATT_GENERIC_WARNING)
236 {
237 DbgPrint("CmBatt: Couldn't allocate pool for registry path.");
238 }
239 return STATUS_INSUFFICIENT_RESOURCES;
240 }
241
242 /* Buffer allocated, copy the string */
243 RtlCopyUnicodeString(&GlobalRegistryPath, RegistryPath);
244 if (CmBattDebug & CMBATT_GENERIC_INFO)
245 {
246 DbgPrint("CmBatt DriverEntry - Obj (%08x) Path \"%ws\"\n",
247 DriverObject,
248 RegistryPath->Buffer);
249 }
250
251 /* Setup the major dispatchers */
252 DriverObject->MajorFunction[0] = CmBattOpenClose;
253 DriverObject->MajorFunction[2] = CmBattOpenClose;
254 DriverObject->MajorFunction[14] = CmBattIoctl;
255 DriverObject->MajorFunction[22] = CmBattPowerDispatch;
256 DriverObject->MajorFunction[27] = CmBattPnpDispatch;
257 DriverObject->MajorFunction[23] = CmBattSystemControl;
258
259 /* And the unload routine */
260 DriverObject->DriverUnload = CmBattUnload;
261
262 /* And the add device routine */
263 DriverExtension = DriverObject->DriverExtension;
264 DriverExtension->AddDevice = CmBattAddDevice;
265
266 /* Create a power callback */
267 RtlInitUnicodeString(&CallbackName, L"\\Callback\\PowerState");
268 InitializeObjectAttributes(&ObjectAttributes,
269 &CallbackName,
270 OBJ_KERNEL_HANDLE,
271 NULL,
272 NULL);
273 Status = ExCreateCallback(&CmBattPowerCallBackObject, &ObjectAttributes, 0, TRUE);
274 if (!NT_SUCCESS(Status))
275 {
276 /* No callback, fail */
277 CmBattPowerCallBackObject = 0;
278 if (CmBattDebug & CMBATT_GENERIC_WARNING)
279 {
280 DbgPrint("CmBattRegisterPowerCallBack: failed status=0x%08x\n", Status);
281 }
282 }
283 else
284 {
285 /* Register the power callback now */
286 CmBattPowerCallBackRegistration = ExRegisterCallback(CmBattPowerCallBackObject,
287 (PVOID)CmBattPowerCallBack,
288 DriverObject);
289 if (CmBattPowerCallBackRegistration)
290 {
291 /* Last thing: setup our DPC and timer for battery wake */
292 KeInitializeDpc(&CmBattWakeDpcObject, (PVOID)CmBattWakeDpc, DriverObject);
293 KeInitializeTimer(&CmBattWakeDpcTimerObject);
294 }
295 else
296 {
297 ObfDereferenceObject(CmBattPowerCallBackObject);
298 if (CmBattDebug & CMBATT_GENERIC_WARNING)
299 {
300 DbgPrint("CmBattRegisterPowerCallBack: ExRegisterCallback failed.\n");
301 }
302 }
303
304 /* All good */
305 Status = STATUS_SUCCESS;
306 }
307
308 /* Return failure or success */
309 return Status;
310 }
311
312 /* EOF */