[THEMES]
[reactos.git] / reactos / drivers / bus / acpi / compbatt / compbatt.c
1 /*
2 * PROJECT: ReactOS Composite Battery Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: boot/drivers/bus/acpi/compbatt/compbatt.c
5 * PURPOSE: Main Initialization Code and IRP Handling
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "compbatt.h"
12
13 /* GLOBALS ********************************************************************/
14
15 ULONG CompBattDebug;
16
17 /* FUNCTIONS ******************************************************************/
18
19 NTSTATUS
20 NTAPI
21 CompBattOpenClose(IN PDEVICE_OBJECT DeviceObject,
22 IN PIRP Irp)
23 {
24 PAGED_CODE();
25 if (CompBattDebug & 0x100) DbgPrint("CompBatt: ENTERING OpenClose\n");
26
27 /* Complete the IRP with success */
28 Irp->IoStatus.Status = STATUS_SUCCESS;
29 Irp->IoStatus.Information = 0;
30 IoCompleteRequest(Irp, IO_NO_INCREMENT);
31
32 /* Return success */
33 if (CompBattDebug & 0x100) DbgPrint("CompBatt: Exiting OpenClose\n");
34 return STATUS_SUCCESS;
35 }
36
37 NTSTATUS
38 NTAPI
39 CompBattSystemControl(IN PDEVICE_OBJECT DeviceObject,
40 IN PIRP Irp)
41 {
42 PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
43 NTSTATUS Status;
44 PAGED_CODE();
45 if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING System Control\n");
46
47 /* Are we attached yet? */
48 if (DeviceExtension->AttachedDevice)
49 {
50 /* Send it up the stack */
51 IoSkipCurrentIrpStackLocation(Irp);
52 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
53 }
54 else
55 {
56 /* We don't support WMI */
57 Status = STATUS_NOT_SUPPORTED;
58 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
59 IoCompleteRequest(Irp, IO_NO_INCREMENT);
60 }
61
62 /* Return status */
63 return Status;
64 }
65
66 NTSTATUS
67 NTAPI
68 CompBattMonitorIrpComplete(IN PDEVICE_OBJECT DeviceObject,
69 IN PIRP Irp,
70 IN PKEVENT Event)
71 {
72 UNIMPLEMENTED;
73 return STATUS_NOT_IMPLEMENTED;
74 }
75
76 NTSTATUS
77 NTAPI
78 CompBattMonitorIrpCompleteWorker(IN PCOMPBATT_BATTERY_DATA BatteryData)
79 {
80 UNIMPLEMENTED;
81 return STATUS_NOT_IMPLEMENTED;
82 }
83
84 VOID
85 NTAPI
86 CompBattRecalculateTag(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
87 {
88 PCOMPBATT_BATTERY_DATA BatteryData;
89 ULONG Tag;
90 PLIST_ENTRY ListHead, NextEntry;
91 if (CompBattDebug & 0x100) DbgPrint("CompBatt: ENTERING CompBattRecalculateTag\n");
92
93 /* Loop the battery list */
94 ExAcquireFastMutex(&DeviceExtension->Lock);
95 ListHead = &DeviceExtension->BatteryList;
96 NextEntry = ListHead->Flink;
97 while (NextEntry != ListHead)
98 {
99 /* Get the battery information and check if it has a tag */
100 BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
101 if (BatteryData->Flags & COMPBATT_TAG_ASSIGNED)
102 {
103 /* Generate the next tag and exit */
104 Tag = DeviceExtension->NextTag;
105 DeviceExtension->Flags |= COMPBATT_TAG_ASSIGNED;
106 DeviceExtension->Tag = Tag;
107 DeviceExtension->NextTag = Tag + 1;
108 break;
109 }
110
111 /* No tag for this device extension, clear it */
112 DeviceExtension->Tag = 0;
113 NextEntry = NextEntry->Flink;
114 }
115
116 /* We're done */
117 ExReleaseFastMutex(&DeviceExtension->Lock);
118 if (CompBattDebug & 0x100) DbgPrint("CompBatt: EXITING CompBattRecalculateTag\n");
119 }
120
121 NTSTATUS
122 NTAPI
123 CompBattIoctl(IN PDEVICE_OBJECT DeviceObject,
124 IN PIRP Irp)
125 {
126 PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
127 NTSTATUS Status;
128 if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING Ioctl\n");
129
130 /* Let the class driver handle it */
131 Status = BatteryClassIoctl(DeviceExtension->ClassData, Irp);
132 if (Status == STATUS_NOT_SUPPORTED)
133 {
134 /* It failed, try the next driver up the stack */
135 Irp->IoStatus.Status = Status;
136 IoSkipCurrentIrpStackLocation(Irp);
137 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
138 }
139
140 /* Return status */
141 if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING Ioctl\n");
142 return Status;
143 }
144
145 NTSTATUS
146 NTAPI
147 CompBattQueryTag(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension,
148 OUT PULONG Tag)
149 {
150 NTSTATUS Status;
151 PAGED_CODE();
152 if (CompBattDebug & 0x100) DbgPrint("CompBatt: ENTERING QueryTag\n");
153
154 /* Was a tag assigned? */
155 if (!(DeviceExtension->Flags & COMPBATT_TAG_ASSIGNED))
156 {
157 /* Assign one */
158 CompBattRecalculateTag(DeviceExtension);
159 }
160
161 /* Do we have a tag now? */
162 if ((DeviceExtension->Flags & COMPBATT_TAG_ASSIGNED) && (DeviceExtension->Tag))
163 {
164 /* Return the tag */
165 *Tag = DeviceExtension->Tag;
166 Status = STATUS_SUCCESS;
167 }
168 else
169 {
170 /* No tag */
171 *Tag = 0;
172 Status = STATUS_NO_SUCH_DEVICE;
173 }
174
175 /* Return status */
176 if (CompBattDebug & 0x100) DbgPrint("CompBatt: EXITING QueryTag\n");
177 return Status;
178 }
179
180 NTSTATUS
181 NTAPI
182 CompBattDisableStatusNotify(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
183 {
184 PCOMPBATT_BATTERY_DATA BatteryData;
185 PLIST_ENTRY ListHead, NextEntry;
186 if (CompBattDebug & 0x100) DbgPrint("CompBatt: ENTERING DisableStatusNotify\n");
187
188 /* Loop the battery list */
189 ExAcquireFastMutex(&DeviceExtension->Lock);
190 ListHead = &DeviceExtension->BatteryList;
191 NextEntry = ListHead->Flink;
192 while (NextEntry != ListHead)
193 {
194 /* Get the battery information and clear capacity data */
195 BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
196 BatteryData->WaitStatus.LowCapacity = 0;
197 BatteryData->WaitStatus.HighCapacity = 0x7FFFFFFF;
198 NextEntry = NextEntry->Flink;
199 }
200
201 /* Done */
202 ExReleaseFastMutex(&DeviceExtension->Lock);
203 if (CompBattDebug & 0x100) DbgPrint("CompBatt: EXITING DisableStatusNotify\n");
204 return STATUS_SUCCESS;
205 }
206
207 NTSTATUS
208 NTAPI
209 CompBattSetStatusNotify(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension,
210 IN ULONG BatteryTag,
211 IN PBATTERY_NOTIFY BatteryNotify)
212 {
213 UNIMPLEMENTED;
214 return STATUS_NOT_IMPLEMENTED;
215 }
216
217 NTSTATUS
218 NTAPI
219 CompBattQueryStatus(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension,
220 IN ULONG Tag,
221 IN PBATTERY_STATUS BatteryStatus)
222 {
223 UNIMPLEMENTED;
224 return STATUS_NOT_IMPLEMENTED;
225 }
226
227 NTSTATUS
228 NTAPI
229 CompBattGetBatteryInformation(OUT PBATTERY_INFORMATION BatteryInfo,
230 IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
231 {
232 NTSTATUS Status = STATUS_SUCCESS;
233 BATTERY_QUERY_INFORMATION InputBuffer;
234 PCOMPBATT_BATTERY_DATA BatteryData;
235 PLIST_ENTRY ListHead, NextEntry;
236 if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING GetBatteryInformation\n");
237
238 /* Set defaults */
239 BatteryInfo->DefaultAlert1 = 0;
240 BatteryInfo->DefaultAlert2 = 0;
241 BatteryInfo->CriticalBias = 0;
242
243 /* Loop the battery list */
244 ExAcquireFastMutex(&DeviceExtension->Lock);
245 ListHead = &DeviceExtension->BatteryList;
246 NextEntry = ListHead->Flink;
247 while (NextEntry != ListHead)
248 {
249 /* Try to acquire the remove lock */
250 BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
251 if (NT_SUCCESS(IoAcquireRemoveLock(&BatteryData->RemoveLock, 0)))
252 {
253 /* Now release the device lock since the battery can't go away */
254 ExReleaseFastMutex(&DeviceExtension->Lock);
255
256 /* Build the query */
257 InputBuffer.BatteryTag = BatteryData->Tag;
258 InputBuffer.InformationLevel = BatteryInformation;
259 InputBuffer.AtRate = 0;
260
261 /* Make sure the battery has a tag */
262 if (BatteryData->Tag)
263 {
264 /* Do we already have the data? */
265 if (!(BatteryData->Flags & COMPBATT_BATTERY_INFORMATION_PRESENT))
266 {
267 /* Send the IOCTL to query the information */
268 RtlZeroMemory(&BatteryData->BatteryInformation,
269 sizeof(BatteryData->BatteryInformation));
270 Status = BatteryIoctl(IOCTL_BATTERY_QUERY_INFORMATION,
271 BatteryData->DeviceObject,
272 &InputBuffer,
273 sizeof(InputBuffer),
274 &BatteryData->BatteryInformation,
275 sizeof(BatteryData->BatteryInformation),
276 0);
277 if (!NT_SUCCESS(Status))
278 {
279 /* Fail if the query had a problem */
280 if (Status == STATUS_DEVICE_REMOVED) Status = STATUS_NO_SUCH_DEVICE;
281 ExAcquireFastMutex(&DeviceExtension->Lock);
282 IoReleaseRemoveLock(&BatteryData->RemoveLock, 0);
283 break;
284 }
285
286 /* Next time we can use the static copy */
287 BatteryData->Flags |= COMPBATT_BATTERY_INFORMATION_PRESENT;
288 if (CompBattDebug & 2)
289 DbgPrint("CompBattGetBatteryInformation: Read individual BATTERY_INFORMATION\n"
290 "-------- Capabilities = %x\n-------- Technology = %x\n"
291 "-------- Chemistry[4] = %x\n-------- DesignedCapacity = %x\n"
292 "-------- FullChargedCapacity = %x\n-------- DefaultAlert1 = %x\n"
293 "-------- DefaultAlert2 = %x\n-------- CriticalBias = %x\n"
294 "-------- CycleCount = %x\n",
295 BatteryData->BatteryInformation.Capabilities,
296 BatteryData->BatteryInformation.Technology,
297 BatteryData->BatteryInformation.Chemistry,
298 BatteryData->BatteryInformation.DesignedCapacity,
299 BatteryData->BatteryInformation.FullChargedCapacity,
300 BatteryData->BatteryInformation.DefaultAlert1,
301 BatteryData->BatteryInformation.DefaultAlert2,
302 BatteryData->BatteryInformation.CriticalBias,
303 BatteryData->BatteryInformation.CycleCount);
304 }
305
306 /* Combine capabilities */
307 BatteryInfo->Capabilities |= BatteryData->BatteryInformation.Capabilities;
308
309 /* Add-on capacity */
310 if (BatteryData->BatteryInformation.DesignedCapacity != BATTERY_UNKNOWN_CAPACITY)
311 {
312 BatteryInfo->DesignedCapacity += BatteryData->BatteryInformation.DesignedCapacity;
313 }
314
315 /* Add on fully charged capacity */
316 if (BatteryData->BatteryInformation.FullChargedCapacity != BATTERY_UNKNOWN_CAPACITY)
317 {
318 BatteryInfo->FullChargedCapacity += BatteryData->BatteryInformation.FullChargedCapacity;
319 }
320
321 /* Choose the highest alert */
322 BatteryInfo->DefaultAlert1 = max(BatteryInfo->DefaultAlert1,
323 BatteryData->BatteryInformation.DefaultAlert1);
324
325 /* Choose the highest alert */
326 BatteryInfo->DefaultAlert2 = max(BatteryInfo->DefaultAlert2,
327 BatteryData->BatteryInformation.DefaultAlert2);
328
329 /* Choose the highest critical bias */
330 BatteryInfo->CriticalBias = max(BatteryInfo->CriticalBias,
331 BatteryData->BatteryInformation.CriticalBias);
332 }
333
334 /* Re-acquire the device extension lock and release the remove lock */
335 ExAcquireFastMutex(&DeviceExtension->Lock);
336 IoReleaseRemoveLock(&BatteryData->RemoveLock, 0);
337 }
338
339 /* Next entry */
340 NextEntry = NextEntry->Flink;
341 }
342
343 /* We are done with the list, check if the information was queried okay */
344 ExReleaseFastMutex(&DeviceExtension->Lock);
345 if (NT_SUCCESS(Status))
346 {
347 /* If there's no fully charged capacity, use the design capacity */
348 if (!BatteryInfo->FullChargedCapacity)
349 {
350 BatteryInfo->FullChargedCapacity = BatteryInfo->DesignedCapacity;
351 }
352
353 /* Print out final combined data */
354 if (CompBattDebug & 2)
355 DbgPrint("CompBattGetBatteryInformation: Returning BATTERY_INFORMATION\n"
356 "-------- Capabilities = %x\n-------- Technology = %x\n"
357 "-------- Chemistry[4] = %x\n-------- DesignedCapacity = %x\n"
358 "-------- FullChargedCapacity = %x\n-------- DefaultAlert1 = %x\n"
359 "-------- DefaultAlert2 = %x\n-------- CriticalBias = %x\n"
360 "-------- CycleCount = %x\n",
361 BatteryInfo->Capabilities,
362 BatteryInfo->Technology,
363 BatteryInfo->Chemistry,
364 BatteryInfo->DesignedCapacity,
365 BatteryInfo->FullChargedCapacity,
366 BatteryInfo->DefaultAlert1,
367 BatteryInfo->DefaultAlert2,
368 BatteryInfo->CriticalBias,
369 BatteryInfo->CycleCount);
370
371 /* Copy the data into the device extension */
372 RtlCopyMemory(&DeviceExtension->BatteryInformation,
373 BatteryInfo,
374 sizeof(DeviceExtension->BatteryInformation));
375 DeviceExtension->Flags |= COMPBATT_BATTERY_INFORMATION_PRESENT;
376 }
377
378 /* We are done */
379 if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING GetBatteryInformation\n");
380 return Status;
381 }
382
383 NTSTATUS
384 NTAPI
385 CompBattGetBatteryGranularity(OUT PBATTERY_REPORTING_SCALE ReportingScale,
386 IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
387 {
388 NTSTATUS Status = STATUS_SUCCESS;
389 BATTERY_QUERY_INFORMATION InputBuffer;
390 PCOMPBATT_BATTERY_DATA BatteryData;
391 BATTERY_REPORTING_SCALE BatteryScale[4];
392 PLIST_ENTRY ListHead, NextEntry;
393 ULONG i;
394 if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING GetBatteryGranularity\n");
395
396 /* Set defaults */
397 ReportingScale[0].Granularity = -1;
398 ReportingScale[1].Granularity = -1;
399 ReportingScale[2].Granularity = -1;
400 ReportingScale[3].Granularity = -1;
401
402 /* Loop the battery list */
403 ExAcquireFastMutex(&DeviceExtension->Lock);
404 ListHead = &DeviceExtension->BatteryList;
405 NextEntry = ListHead->Flink;
406 while (NextEntry != ListHead)
407 {
408 /* Try to acquire the remove lock */
409 BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
410 if (NT_SUCCESS(IoAcquireRemoveLock(&BatteryData->RemoveLock, 0)))
411 {
412 /* Now release the device lock since the battery can't go away */
413 ExReleaseFastMutex(&DeviceExtension->Lock);
414
415 /* Build the query */
416 InputBuffer.BatteryTag = BatteryData->Tag;
417 InputBuffer.InformationLevel = BatteryGranularityInformation;
418
419 /* Make sure the battery has a tag */
420 if (BatteryData->Tag)
421 {
422 /* Send the IOCTL to query the information */
423 RtlZeroMemory(&BatteryData->BatteryInformation,
424 sizeof(BatteryData->BatteryInformation));
425 Status = BatteryIoctl(IOCTL_BATTERY_QUERY_INFORMATION,
426 BatteryData->DeviceObject,
427 &InputBuffer,
428 sizeof(InputBuffer),
429 &BatteryScale,
430 sizeof(BatteryScale),
431 0);
432 if (!NT_SUCCESS(Status))
433 {
434 /* Fail if the query had a problem */
435 ExAcquireFastMutex(&DeviceExtension->Lock);
436 IoReleaseRemoveLock(&BatteryData->RemoveLock, 0);
437 break;
438 }
439
440 /* Loop all 4 scales */
441 for (i = 0; i < 4; i++)
442 {
443 /* Check for valid granularity */
444 if (BatteryScale[i].Granularity)
445 {
446 /* If it's smaller, use it instead */
447 ReportingScale[i].Granularity = min(BatteryScale[i].Granularity,
448 ReportingScale[i].Granularity);
449 }
450
451 }
452 }
453
454 /* Re-acquire the device extension lock and release the remove lock */
455 ExAcquireFastMutex(&DeviceExtension->Lock);
456 IoReleaseRemoveLock(&BatteryData->RemoveLock, 0);
457 }
458
459 /* Next entry */
460 NextEntry = NextEntry->Flink;
461 }
462
463 /* All done */
464 ExReleaseFastMutex(&DeviceExtension->Lock);
465 if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING GetBatteryGranularity\n");
466 return STATUS_SUCCESS;
467 }
468
469 NTSTATUS
470 NTAPI
471 CompBattGetEstimatedTime(OUT PULONG Time,
472 IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
473 {
474 UNIMPLEMENTED;
475 return STATUS_NOT_IMPLEMENTED;
476 }
477
478 NTSTATUS
479 NTAPI
480 CompBattQueryInformation(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension,
481 IN ULONG Tag,
482 IN BATTERY_QUERY_INFORMATION_LEVEL InfoLevel,
483 IN OPTIONAL LONG AtRate,
484 IN PVOID Buffer,
485 IN ULONG BufferLength,
486 OUT PULONG ReturnedLength)
487 {
488 BATTERY_INFORMATION BatteryInfo;
489 BATTERY_REPORTING_SCALE BatteryGranularity[4];
490 PWCHAR BatteryName = L"Composite Battery";
491 //BATTERY_MANUFACTURE_DATE Date;
492 ULONG Dummy, Time;
493 PVOID QueryData = NULL;
494 ULONG QueryLength = 0;
495 NTSTATUS Status = STATUS_SUCCESS;
496 PAGED_CODE();
497 if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING QueryInformation\n");
498
499 /* Check for valid/correct tag */
500 if ((Tag != DeviceExtension->Tag) ||
501 (!(DeviceExtension->Flags & COMPBATT_TAG_ASSIGNED)))
502 {
503 /* Not right, so fail */
504 return STATUS_NO_SUCH_DEVICE;
505 }
506
507 /* Check what caller wants */
508 switch (InfoLevel)
509 {
510 case BatteryInformation:
511
512 /* Query combined battery information */
513 RtlZeroMemory(&BatteryInfo, sizeof(BatteryInfo));
514 Status = CompBattGetBatteryInformation(&BatteryInfo, DeviceExtension);
515 if (NT_SUCCESS(Status))
516 {
517 /* Return the data if successful */
518 QueryData = &BatteryInfo;
519 QueryLength = sizeof(BatteryInfo);
520 }
521 break;
522
523 case BatteryGranularityInformation:
524
525 /* Query combined granularity information */
526 RtlZeroMemory(&BatteryGranularity, sizeof(BatteryGranularity));
527 Status = CompBattGetBatteryGranularity(BatteryGranularity, DeviceExtension);
528 if (NT_SUCCESS(Status))
529 {
530 /* Return the data if successful */
531 QueryLength = sizeof(BatteryGranularity);
532 QueryData = &BatteryGranularity;
533 }
534 break;
535
536 case BatteryEstimatedTime:
537
538 /* Query combined time estimate information */
539 RtlZeroMemory(&Time, sizeof(Time));
540 Status = CompBattGetEstimatedTime(&Time, DeviceExtension);
541 if (NT_SUCCESS(Status))
542 {
543 /* Return the data if successful */
544 QueryLength = sizeof(Time);
545 QueryData = &Time;
546 }
547 break;
548
549 case BatteryManufactureName:
550 case BatteryDeviceName:
551
552 /* Return the static buffer */
553 QueryData = BatteryName;
554 QueryLength = sizeof(L"Composite Battery");
555 break;
556
557 case BatteryManufactureDate:
558
559 /* Static data */
560 //Date.Day = 26;
561 //Date.Month = 06;
562 //Date.Year = 1997;
563 break;
564
565 case BatteryTemperature:
566 case BatteryUniqueID:
567
568 /* Return zero */
569 Dummy = 0;
570 QueryData = &Dummy;
571 QueryLength = sizeof(Dummy);
572 break;
573
574 default:
575 /* Everything else is unknown */
576 Status = STATUS_INVALID_PARAMETER;
577 break;
578 }
579
580 /* Return the required length and check if the caller supplied enough */
581 *ReturnedLength = QueryLength;
582 if (BufferLength < QueryLength) Status = STATUS_BUFFER_TOO_SMALL;
583
584 /* Copy the data if there's enough space and it exists */
585 if ((NT_SUCCESS(Status)) && (QueryData)) RtlCopyMemory(Buffer, QueryData, QueryLength);
586
587 /* Return function result */
588 if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING QueryInformation\n");
589 return Status;
590 }
591
592 NTSTATUS
593 NTAPI
594 DriverEntry(IN PDRIVER_OBJECT DriverObject,
595 IN PUNICODE_STRING RegistryPath)
596 {
597 /* Register add device routine */
598 DriverObject->DriverExtension->AddDevice = CompBattAddDevice;
599
600 /* Register other handlers */
601 DriverObject->MajorFunction[IRP_MJ_CREATE] = CompBattOpenClose;
602 DriverObject->MajorFunction[IRP_MJ_CLOSE] = CompBattOpenClose;
603 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CompBattIoctl;
604 DriverObject->MajorFunction[IRP_MJ_POWER] = CompBattPowerDispatch;
605 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = CompBattSystemControl;
606 DriverObject->MajorFunction[IRP_MJ_PNP] = CompBattPnpDispatch;
607 return STATUS_SUCCESS;
608 }
609
610 /* EOF */