[CMBATT]
authorCameron Gutman <aicommander@gmail.com>
Mon, 8 Mar 2010 21:09:25 +0000 (21:09 +0000)
committerCameron Gutman <aicommander@gmail.com>
Mon, 8 Mar 2010 21:09:25 +0000 (21:09 +0000)
 - Add initial cmbatt driver which mostly stubs
 - All it does right now is register a battery device with the battc driver
[BATTC]
 - Add a nearly complete battc driver (the only stuff missing is WMI)
 - Tested with our stubbed cmbatt driver but testing on Windows would be nice too
[BATTERY.INF]
 - Added battery.inf to install battery devices
[MISC]
 - Add cmbatt.sys, battc.sys, and battery.inf to bootcd
 - We still need to implement compbatt.sys
 - PS: Janderwald, you stole my commit number ;)

svn path=/trunk/; revision=46011

14 files changed:
reactos/boot/bootdata/packages/reactos.dff
reactos/drivers/battery/battc/battc.c [new file with mode: 0644]
reactos/drivers/battery/battc/battc.h [new file with mode: 0644]
reactos/drivers/battery/battc/battc.rbuild [new file with mode: 0644]
reactos/drivers/battery/battc/battc.rc [new file with mode: 0644]
reactos/drivers/battery/battc/battc.spec [new file with mode: 0644]
reactos/drivers/battery/cmbatt/cmbatt.c [new file with mode: 0644]
reactos/drivers/battery/cmbatt/cmbatt.h [new file with mode: 0644]
reactos/drivers/battery/cmbatt/cmbatt.rbuild [new file with mode: 0644]
reactos/drivers/battery/cmbatt/cmbatt.rc [new file with mode: 0644]
reactos/drivers/battery/cmbatt/miniclass.c [new file with mode: 0644]
reactos/drivers/battery/directory.rbuild [new file with mode: 0644]
reactos/drivers/drivers.rbuild
reactos/media/inf/battery.inf [new file with mode: 0644]

index a0db0df..c8be7bd 100644 (file)
@@ -482,6 +482,9 @@ drivers\base\beep\beep.sys                          2
 drivers\base\null\null.sys                          2
 drivers\base\nmidebug\nmidebug.sys                  2
 
+drivers\battery\cmbatt\cmbatt.sys                   2
+drivers\battery\battc\battc.sys                     2
+
 drivers\bus\isapnp\isapnp.sys                       2
 
 drivers\directx\dxapi\dxapi.sys                     2
@@ -628,6 +631,7 @@ media\nls\c_28606.nls                               1
 media\drivers\etc\services                          5
 media\inf\audio.inf                                 6
 media\inf\acpi.inf                                  6
+media\inf\battery.inf                               6
 media\inf\cdrom.inf                                 6
 media\inf\cpu.inf                                   6
 media\inf\display.inf                               6
diff --git a/reactos/drivers/battery/battc/battc.c b/reactos/drivers/battery/battc/battc.c
new file mode 100644 (file)
index 0000000..a626d8c
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            drivers/battery/battc/battc.c
+ * PURPOSE:         Battery Class Driver
+ * PROGRAMMERS:     Cameron Gutman (cameron.gutman@reactos.org)
+ */
+
+#include <battc.h>
+
+#define NDEBUG
+#include <debug.h>
+
+NTSTATUS
+NTAPI
+DriverEntry(PDRIVER_OBJECT DriverObject,
+            PUNICODE_STRING RegistryPath)
+{
+  DPRINT("Battery class driver initialized\n");
+
+  return STATUS_SUCCESS;
+}
+
+BCLASSAPI
+NTSTATUS
+DDKAPI
+BatteryClassUnload(PVOID ClassData)
+{
+  PBATTERY_CLASS_DATA BattClass = ClassData;
+
+  DPRINT("Battery 0x%x is being unloaded\n");
+
+  if (BattClass->InterfaceName.Length != 0)
+  {
+      IoSetDeviceInterfaceState(&BattClass->InterfaceName, FALSE);
+      RtlFreeUnicodeString(&BattClass->InterfaceName);
+  }
+
+  ExFreePoolWithTag(BattClass,
+                    BATTERY_CLASS_DATA_TAG);
+
+  return STATUS_SUCCESS;
+}
+
+BCLASSAPI
+NTSTATUS
+DDKAPI
+BatteryClassSystemControl(PVOID ClassData,
+                          PWMILIB_CONTEXT WmiLibContext,
+                          PDEVICE_OBJECT DeviceObject,
+                          PIRP Irp,
+                          PSYSCTL_IRP_DISPOSITION Disposition)
+{
+  NTSTATUS Status;
+
+  UNIMPLEMENTED
+
+  /* FIXME: Uncomment when WmiCompleteRequest is implemented */
+#if 0
+  Status = STATUS_WMI_GUID_NOT_FOUND;
+  WmiCompleteRequest(DeviceObject,
+                     Irp,
+                     Status,
+                     0,
+                     IO_NO_INCREMENT);
+#else
+  Irp->IoStatus.Status = Status = STATUS_WMI_GUID_NOT_FOUND;
+  Irp->IoStatus.Information = 0;
+
+  IoCompleteRequest(Irp, IO_NO_INCREMENT);
+#endif
+
+  return Status;
+}
+
+BCLASSAPI
+NTSTATUS
+DDKAPI
+BatteryClassQueryWmiDataBlock(PVOID ClassData,
+                              PDEVICE_OBJECT DeviceObject,
+                              PIRP Irp,
+                              ULONG GuidIndex,
+                              PULONG InstanceLengthArray,
+                              ULONG OutBufferSize,
+                              PUCHAR Buffer)
+{
+  UNIMPLEMENTED
+
+  return STATUS_WMI_GUID_NOT_FOUND;
+}
+
+BCLASSAPI
+NTSTATUS
+DDKAPI
+BatteryClassStatusNotify(PVOID ClassData)
+{
+  PBATTERY_CLASS_DATA BattClass = ClassData;
+  PBATTERY_WAIT_STATUS BattWait = BattClass->EventTriggerContext;
+  BATTERY_STATUS BattStatus;
+  NTSTATUS Status;
+
+  DPRINT("Received battery status notification from 0x%x\n", ClassData);
+
+  ExAcquireFastMutex(&BattClass->Mutex);
+  if (!BattClass->Waiting)
+  {
+      ExReleaseFastMutex(&BattClass->Mutex);
+      return STATUS_SUCCESS;
+  }
+
+  switch (BattClass->EventTrigger)
+  {
+     case EVENT_BATTERY_TAG:
+       ExReleaseFastMutex(&BattClass->Mutex);
+       DPRINT1("Waiting for battery is UNIMPLEMENTED!\n");
+       break;
+
+     case EVENT_BATTERY_STATUS:
+       ExReleaseFastMutex(&BattClass->Mutex);
+       Status = BattClass->MiniportInfo.QueryStatus(BattClass->MiniportInfo.Context,
+                                                    BattWait->BatteryTag,
+                                                    &BattStatus);
+       if (!NT_SUCCESS(Status))
+           return Status;
+
+       ExAcquireFastMutex(&BattClass->Mutex);
+
+       if (!(BattWait->PowerState & BattStatus.PowerState) ||
+           (BattWait->HighCapacity > BattStatus.Capacity) ||
+           (BattWait->LowCapacity < BattStatus.Capacity))
+       {
+           KeSetEvent(&BattClass->WaitEvent, IO_NO_INCREMENT, FALSE);
+       }
+
+       ExReleaseFastMutex(&BattClass->Mutex);
+       break;
+
+     default:
+       ExReleaseFastMutex(&BattClass->Mutex);
+       ASSERT(FALSE);
+       break;
+  }
+
+  return STATUS_SUCCESS;
+}
+
+BCLASSAPI
+NTSTATUS
+DDKAPI
+BatteryClassInitializeDevice(PBATTERY_MINIPORT_INFO MiniportInfo,
+                             PVOID *ClassData)
+{
+  NTSTATUS Status;
+  PBATTERY_CLASS_DATA BattClass = ExAllocatePoolWithTag(NonPagedPool,
+                                                        sizeof(BATTERY_CLASS_DATA),
+                                                        BATTERY_CLASS_DATA_TAG);
+
+  if (!BattClass)
+      return STATUS_INSUFFICIENT_RESOURCES;
+
+  RtlZeroMemory(BattClass, sizeof(BATTERY_CLASS_DATA));
+
+  RtlCopyMemory(&BattClass->MiniportInfo,
+                MiniportInfo,
+                sizeof(BattClass->MiniportInfo));
+
+  KeInitializeEvent(&BattClass->WaitEvent, SynchronizationEvent, FALSE);
+
+  ExInitializeFastMutex(&BattClass->Mutex);
+
+  Status = IoRegisterDeviceInterface(MiniportInfo->Pdo,
+                                     &GUID_DEVICE_BATTERY,
+                                     NULL,
+                                     &BattClass->InterfaceName);
+  if (NT_SUCCESS(Status))
+  {
+      DPRINT("Initialized battery interface: %wZ\n", &BattClass->InterfaceName);
+      IoSetDeviceInterfaceState(&BattClass->InterfaceName, TRUE);
+  }
+  else
+  {
+      DPRINT1("IoRegisterDeviceInterface failed (0x%x)\n", Status);
+  }
+
+  *ClassData = BattClass;
+
+  return STATUS_SUCCESS;
+}
+
+BCLASSAPI
+NTSTATUS
+DDKAPI
+BatteryClassIoctl(PVOID ClassData,
+                  PIRP Irp)
+{
+  PBATTERY_CLASS_DATA BattClass = ClassData;
+  PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
+  NTSTATUS Status;
+  ULONG WaitTime;
+  PBATTERY_WAIT_STATUS BattWait;
+  PBATTERY_QUERY_INFORMATION BattQueryInfo;
+  PBATTERY_SET_INFORMATION BattSetInfo;
+  LARGE_INTEGER Timeout;
+  PBATTERY_STATUS BattStatus;
+  BATTERY_NOTIFY BattNotify;
+
+  Irp->IoStatus.Information = 0;
+
+  DPRINT("Received IOCTL %x for 0x%x\n", IrpSp->Parameters.DeviceIoControl.IoControlCode,
+         ClassData);
+
+  switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
+  {
+    case IOCTL_BATTERY_QUERY_TAG:
+      if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG) ||
+          IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
+      {
+          Status = STATUS_BUFFER_TOO_SMALL;
+          break;
+      }
+
+      WaitTime = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
+
+      Timeout.QuadPart = Int32x32To64(WaitTime, -1000);
+
+      Status = BattClass->MiniportInfo.QueryTag(BattClass->MiniportInfo.Context,
+                                                (PULONG)Irp->AssociatedIrp.SystemBuffer);
+      if (!NT_SUCCESS(Status))
+      {
+          ExAcquireFastMutex(&BattClass->Mutex);
+          BattClass->EventTrigger = EVENT_BATTERY_TAG;
+          BattClass->Waiting = TRUE;
+          ExReleaseFastMutex(&BattClass->Mutex);
+
+          Status = KeWaitForSingleObject(&BattClass->WaitEvent,
+                                         Executive,
+                                         KernelMode,
+                                         FALSE,
+                                         WaitTime != -1 ? &Timeout : NULL);
+
+          ExAcquireFastMutex(&BattClass->Mutex);
+          BattClass->Waiting = FALSE;
+          ExReleaseFastMutex(&BattClass->Mutex);
+
+          if (Status == STATUS_SUCCESS)
+          {
+              Status = BattClass->MiniportInfo.QueryTag(BattClass->MiniportInfo.Context,
+                                                        (PULONG)Irp->AssociatedIrp.SystemBuffer);
+              if (NT_SUCCESS(Status))
+                  Irp->IoStatus.Information = sizeof(ULONG);
+          }
+          else
+          {
+              Status = STATUS_NO_SUCH_DEVICE;
+          }
+      }
+      else
+          Irp->IoStatus.Information = sizeof(ULONG);
+      break;
+
+    case IOCTL_BATTERY_QUERY_STATUS:
+      if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(*BattWait) ||
+          IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(BATTERY_STATUS))
+      {
+          Status = STATUS_BUFFER_TOO_SMALL;
+          break;
+      }
+
+      BattWait = Irp->AssociatedIrp.SystemBuffer;
+
+      Timeout.QuadPart = Int32x32To64(BattWait->Timeout, -1000);
+
+      Status = BattClass->MiniportInfo.QueryStatus(BattClass->MiniportInfo.Context,
+                                                   BattWait->BatteryTag,
+                                                   (PBATTERY_STATUS)Irp->AssociatedIrp.SystemBuffer);
+
+      BattStatus = Irp->AssociatedIrp.SystemBuffer;
+
+      if (!NT_SUCCESS(Status) ||
+          ((BattWait->PowerState & BattStatus->PowerState) &&
+           (BattWait->HighCapacity <= BattStatus->Capacity) &&
+           (BattWait->LowCapacity >= BattStatus->Capacity)))
+      {
+          BattNotify.PowerState = BattWait->PowerState;
+          BattNotify.HighCapacity = BattWait->HighCapacity;
+          BattNotify.LowCapacity = BattWait->LowCapacity;
+
+          BattClass->MiniportInfo.SetStatusNotify(BattClass->MiniportInfo.Context,
+                                                  BattWait->BatteryTag,
+                                                  &BattNotify);
+
+          ExAcquireFastMutex(&BattClass->Mutex);
+          BattClass->EventTrigger = EVENT_BATTERY_STATUS;
+          BattClass->EventTriggerContext = BattWait;
+          BattClass->Waiting = TRUE;
+          ExReleaseFastMutex(&BattClass->Mutex);
+
+          Status = KeWaitForSingleObject(&BattClass->WaitEvent,
+                                         Executive,
+                                         KernelMode,
+                                         FALSE,
+                                         BattWait->Timeout != -1 ? &Timeout : NULL);
+
+          ExAcquireFastMutex(&BattClass->Mutex);
+          BattClass->Waiting = FALSE;
+          ExReleaseFastMutex(&BattClass->Mutex);
+
+          BattClass->MiniportInfo.DisableStatusNotify(BattClass->MiniportInfo.Context);
+
+          if (Status == STATUS_SUCCESS)
+          {
+              Status = BattClass->MiniportInfo.QueryStatus(BattClass->MiniportInfo.Context,
+                                                           BattWait->BatteryTag,
+                                                           (PBATTERY_STATUS)Irp->AssociatedIrp.SystemBuffer);
+              if (NT_SUCCESS(Status))
+                  Irp->IoStatus.Information = sizeof(ULONG);
+          }
+          else
+          {
+              Status = STATUS_NO_SUCH_DEVICE;
+          }
+      }
+      else
+          Irp->IoStatus.Information = sizeof(BATTERY_STATUS);
+      break;
+
+    case IOCTL_BATTERY_QUERY_INFORMATION:
+      if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(*BattQueryInfo))
+      {
+          Status = STATUS_BUFFER_TOO_SMALL;
+          break;
+      }
+
+      BattQueryInfo = Irp->AssociatedIrp.SystemBuffer;
+
+      Status = BattClass->MiniportInfo.QueryInformation(BattClass->MiniportInfo.Context,
+                                                        BattQueryInfo->BatteryTag,
+                                                        BattQueryInfo->InformationLevel,
+                                                        BattQueryInfo->AtRate,
+                                                        Irp->AssociatedIrp.SystemBuffer,
+                                                        IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
+                                                        &Irp->IoStatus.Information);
+      if (!NT_SUCCESS(Status))
+          DPRINT1("QueryInformation failed (0x%x)\n", Status);
+      break;
+    case IOCTL_BATTERY_SET_INFORMATION:
+      if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(*BattSetInfo))
+      {
+          Status = STATUS_BUFFER_TOO_SMALL;
+          break;
+      }
+
+      BattSetInfo = Irp->AssociatedIrp.SystemBuffer;
+
+      Status = BattClass->MiniportInfo.SetInformation(BattClass->MiniportInfo.Context,
+                                                      BattSetInfo->BatteryTag,
+                                                      BattSetInfo->InformationLevel,
+                                                      BattSetInfo->Buffer);
+      if (!NT_SUCCESS(Status))
+          DPRINT1("SetInformation failed (0x%x)\n", Status);
+      break;
+
+    default:
+      DPRINT1("Received unsupported IRP %x\n", IrpSp->Parameters.DeviceIoControl.IoControlCode);
+      /* Do NOT complete the irp */
+      return STATUS_NOT_SUPPORTED;
+  }
+
+  Irp->IoStatus.Status = Status;
+  IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+  return Status;
+}
diff --git a/reactos/drivers/battery/battc/battc.h b/reactos/drivers/battery/battc/battc.h
new file mode 100644 (file)
index 0000000..b7c5af4
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+* PROJECT:         ReactOS Kernel
+* LICENSE:         GPL - See COPYING in the top level directory
+* FILE:            drivers/battery/battc/battc.h
+* PURPOSE:         Battery Class Driver
+* PROGRAMMERS:     Cameron Gutman (cameron.gutman@reactos.org)
+*/
+
+#pragma once
+
+#include <ntddk.h>
+#include <initguid.h>
+#include <batclass.h>
+
+typedef struct _BATTERY_CLASS_DATA {
+  BATTERY_MINIPORT_INFO MiniportInfo;
+  KEVENT WaitEvent;
+  BOOLEAN Waiting;
+  FAST_MUTEX Mutex;
+  UCHAR EventTrigger;
+  PVOID EventTriggerContext;
+  UNICODE_STRING InterfaceName;
+} BATTERY_CLASS_DATA, *PBATTERY_CLASS_DATA;
+
+/* Memory tags */
+#define BATTERY_CLASS_DATA_TAG 'CtaB'
+
+/* Event triggers */
+#define EVENT_BATTERY_TAG    0x01
+#define EVENT_BATTERY_STATUS 0x02
diff --git a/reactos/drivers/battery/battc/battc.rbuild b/reactos/drivers/battery/battc/battc.rbuild
new file mode 100644 (file)
index 0000000..c026134
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
+<module name="battc" type="kernelmodedriver" installbase="system32/drivers" installname="battc.sys">
+       <library>ntoskrnl</library>
+       <library>hal</library>
+       <importlibrary definition="battc.spec"/>
+       <include base="battc">.</include>
+       <file>battc.c</file>
+       <file>battc.rc</file>
+</module>
diff --git a/reactos/drivers/battery/battc/battc.rc b/reactos/drivers/battery/battc/battc.rc
new file mode 100644 (file)
index 0000000..2230092
--- /dev/null
@@ -0,0 +1,5 @@
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION   "Battery Class Driver\0"
+#define REACTOS_STR_INTERNAL_NAME      "battc\0"
+#define REACTOS_STR_ORIGINAL_FILENAME  "battc.sys\0"
+#include <reactos/version.rc>
diff --git a/reactos/drivers/battery/battc/battc.spec b/reactos/drivers/battery/battc/battc.spec
new file mode 100644 (file)
index 0000000..c2d21b7
--- /dev/null
@@ -0,0 +1,6 @@
+@ stdcall BatteryClassInitializeDevice(ptr ptr)
+@ stdcall BatteryClassIoctl(ptr ptr)
+@ stdcall BatteryClassQueryWmiDataBlock(ptr ptr ptr long ptr long ptr)
+@ stdcall BatteryClassStatusNotify(ptr)
+@ stdcall BatteryClassSystemControl(ptr ptr ptr ptr ptr)
+@ stdcall BatteryClassUnload(ptr)
diff --git a/reactos/drivers/battery/cmbatt/cmbatt.c b/reactos/drivers/battery/cmbatt/cmbatt.c
new file mode 100644 (file)
index 0000000..b85f3eb
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            drivers/battery/cmbatt/cmbatt.c
+ * PURPOSE:         Control Method Battery Miniclass Driver
+ * PROGRAMMERS:     Cameron Gutman (cameron.gutman@reactos.org)
+ */
+
+#include <cmbatt.h>
+
+#define NDEBUG
+#include <debug.h>
+
+LIST_ENTRY BatteryList;
+KSPIN_LOCK BatteryListLock;
+
+VOID
+NTAPI
+CmBattUnload(PDRIVER_OBJECT DriverObject)
+{
+  DPRINT("Control method battery miniclass driver unloaded\n");
+}
+
+NTSTATUS
+NTAPI
+CmBattDeviceControl(PDEVICE_OBJECT DeviceObject,
+                    PIRP Irp)
+{
+  PCMBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+  NTSTATUS Status;
+
+  Status = BatteryClassIoctl(DeviceExtension->BattClassHandle,
+                             Irp);
+
+  if (Status == STATUS_NOT_SUPPORTED)
+  {
+      Irp->IoStatus.Status = Status;
+      Irp->IoStatus.Information = 0;
+
+      IoCompleteRequest(Irp, IO_NO_INCREMENT);
+  }
+
+  return Status;
+}
+
+NTSTATUS
+NTAPI
+CmBattPnP(PDEVICE_OBJECT DeviceObject,
+          PIRP Irp)
+{
+  PCMBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+
+  UNIMPLEMENTED
+
+  IoSkipCurrentIrpStackLocation(Irp);
+
+  return IoCallDriver(DeviceExtension->Ldo, Irp);
+}
+
+NTSTATUS
+NTAPI
+CmBattSystemControl(PDEVICE_OBJECT DeviceObject,
+                    PIRP Irp)
+{
+  UNIMPLEMENTED
+
+  Irp->IoStatus.Status = STATUS_WMI_GUID_NOT_FOUND;
+  Irp->IoStatus.Information = 0;
+
+  IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+  return STATUS_WMI_GUID_NOT_FOUND;
+}
+
+NTSTATUS
+NTAPI
+CmBattPower(PDEVICE_OBJECT DeviceObject,
+            PIRP Irp)
+{
+  PCMBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+
+  UNIMPLEMENTED
+
+  IoSkipCurrentIrpStackLocation(Irp);
+
+  PoStartNextPowerIrp(Irp);
+
+  return PoCallDriver(DeviceExtension->Ldo, Irp);
+}
+
+NTSTATUS
+NTAPI
+CmBattCreateClose(PDEVICE_OBJECT DeviceObject,
+                  PIRP Irp)
+{
+  Irp->IoStatus.Status = STATUS_SUCCESS;
+  Irp->IoStatus.Information = 0;
+
+  IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+  return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+CmBattAddDevice(PDRIVER_OBJECT DriverObject,
+                PDEVICE_OBJECT PhysicalDeviceObject)
+{
+  NTSTATUS Status;
+  PDEVICE_OBJECT DeviceObject;
+  PCMBATT_DEVICE_EXTENSION DeviceExtension;
+  BATTERY_MINIPORT_INFO BattInfo;
+
+  Status = IoCreateDevice(DriverObject,
+                          sizeof(CMBATT_DEVICE_EXTENSION),
+                          NULL,
+                          FILE_DEVICE_BATTERY,
+                          0,
+                          FALSE,
+                          &DeviceObject);
+  if (!NT_SUCCESS(Status))
+      return Status;
+
+  DeviceExtension = DeviceObject->DeviceExtension;
+
+  DeviceExtension->Pdo = PhysicalDeviceObject;
+  DeviceExtension->Fdo = DeviceObject;
+  DeviceExtension->Ldo = IoAttachDeviceToDeviceStack(DeviceObject,
+                                                     PhysicalDeviceObject);
+
+  DeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
+
+  /* We require an extra stack entry */
+  DeviceObject->StackSize = PhysicalDeviceObject->StackSize + 2;
+
+  BattInfo.MajorVersion = BATTERY_CLASS_MAJOR_VERSION;
+  BattInfo.MinorVersion = BATTERY_CLASS_MINOR_VERSION;
+  BattInfo.Context = DeviceExtension;
+  BattInfo.QueryTag = CmBattQueryTag;
+  BattInfo.QueryInformation = CmBattQueryInformation;
+  BattInfo.SetInformation = CmBattSetInformation;
+  BattInfo.QueryStatus = CmBattQueryStatus;
+  BattInfo.SetStatusNotify = CmBattSetStatusNotify;
+  BattInfo.DisableStatusNotify = CmBattDisableStatusNotify;
+  BattInfo.Pdo = PhysicalDeviceObject;
+  BattInfo.DeviceName = NULL;
+
+  Status = BatteryClassInitializeDevice(&BattInfo,
+                                        &DeviceExtension->BattClassHandle);
+  if (!NT_SUCCESS(Status))
+  {
+     IoDetachDevice(DeviceExtension->Ldo);
+     IoDeleteDevice(DeviceObject);
+     return Status;
+  }
+
+  ExInterlockedInsertTailList(&BatteryList,
+                              &DeviceExtension->ListEntry,
+                              &BatteryListLock);
+
+  DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+
+  DPRINT("Successfully registered battery with battc (0x%x)\n", DeviceExtension->BattClassHandle);
+
+  return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+DriverEntry(PDRIVER_OBJECT DriverObject,
+            PUNICODE_STRING RegistryPath)
+{
+  DPRINT("Control method battery miniclass driver initialized\n");
+
+  DriverObject->DriverUnload = CmBattUnload;
+  DriverObject->DriverExtension->AddDevice = CmBattAddDevice;
+  DriverObject->MajorFunction[IRP_MJ_POWER] = CmBattPower;
+  DriverObject->MajorFunction[IRP_MJ_PNP] = CmBattPnP;
+  DriverObject->MajorFunction[IRP_MJ_CREATE] = CmBattCreateClose;
+  DriverObject->MajorFunction[IRP_MJ_CLOSE] = CmBattCreateClose;
+  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CmBattDeviceControl;
+  DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = CmBattSystemControl;
+
+  KeInitializeSpinLock(&BatteryListLock);
+  InitializeListHead(&BatteryList);
+
+  return STATUS_SUCCESS;
+}
diff --git a/reactos/drivers/battery/cmbatt/cmbatt.h b/reactos/drivers/battery/cmbatt/cmbatt.h
new file mode 100644 (file)
index 0000000..e70b561
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+* PROJECT:         ReactOS Kernel
+* LICENSE:         GPL - See COPYING in the top level directory
+* FILE:            drivers/battery/cmbatt/cmbatt.h
+* PURPOSE:         Control Method Battery Miniclass Driver
+* PROGRAMMERS:     Cameron Gutman (cameron.gutman@reactos.org)
+*/
+
+#pragma once
+
+#include <ntddk.h>
+#include <batclass.h>
+
+typedef struct _CMBATT_DEVICE_EXTENSION {
+  PDEVICE_OBJECT Pdo;
+  PDEVICE_OBJECT Ldo;
+  PDEVICE_OBJECT Fdo;
+  PVOID BattClassHandle;
+  LIST_ENTRY ListEntry;
+} CMBATT_DEVICE_EXTENSION, *PCMBATT_DEVICE_EXTENSION;
+
+NTSTATUS
+NTAPI
+CmBattQueryTag(PVOID Context,
+               PULONG BatteryTag);
+
+NTSTATUS
+NTAPI
+CmBattDisableStatusNotify(PVOID Context);
+
+NTSTATUS
+NTAPI
+CmBattSetStatusNotify(PVOID Context,
+                      ULONG BatteryTag,
+                      PBATTERY_NOTIFY BatteryNotify);
+
+NTSTATUS
+NTAPI
+CmBattQueryInformation(PVOID Context,
+                       ULONG BatteryTag,
+                       BATTERY_QUERY_INFORMATION_LEVEL Level,
+                       OPTIONAL LONG AtRate,
+                       PVOID Buffer,
+                       ULONG BufferLength,
+                       PULONG ReturnedLength);
+
+NTSTATUS
+NTAPI
+CmBattQueryStatus(PVOID Context,
+                  ULONG BatteryTag,
+                  PBATTERY_STATUS BatteryStatus);
+
+NTSTATUS
+NTAPI
+CmBattSetInformation(PVOID Context,
+                     ULONG BatteryTag,
+                     BATTERY_SET_INFORMATION_LEVEL Level,
+                     OPTIONAL PVOID Buffer);
diff --git a/reactos/drivers/battery/cmbatt/cmbatt.rbuild b/reactos/drivers/battery/cmbatt/cmbatt.rbuild
new file mode 100644 (file)
index 0000000..c41a072
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
+<module name="cmbatt" type="kernelmodedriver" installbase="system32/drivers" installname="cmbatt.sys">
+       <library>ntoskrnl</library>
+       <library>hal</library>
+       <library>battc</library>
+       <include base="cmbatt">.</include>
+       <file>cmbatt.c</file>
+       <file>miniclass.c</file>
+       <file>cmbatt.rc</file>
+</module>
diff --git a/reactos/drivers/battery/cmbatt/cmbatt.rc b/reactos/drivers/battery/cmbatt/cmbatt.rc
new file mode 100644 (file)
index 0000000..2fd6bc7
--- /dev/null
@@ -0,0 +1,5 @@
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION   "Control Method Battery Miniclass Driver\0"
+#define REACTOS_STR_INTERNAL_NAME      "cmbatt\0"
+#define REACTOS_STR_ORIGINAL_FILENAME  "cmbatt.sys\0"
+#include <reactos/version.rc>
diff --git a/reactos/drivers/battery/cmbatt/miniclass.c b/reactos/drivers/battery/cmbatt/miniclass.c
new file mode 100644 (file)
index 0000000..bb75d9a
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            drivers/battery/cmbatt/miniclass.c
+ * PURPOSE:         Control Method Battery Miniclass Driver
+ * PROGRAMMERS:     Cameron Gutman (cameron.gutman@reactos.org)
+ */
+
+#include <cmbatt.h>
+
+#define NDEBUG
+#include <debug.h>
+
+NTSTATUS
+NTAPI
+CmBattQueryTag(PVOID Context,
+               PULONG BatteryTag)
+{
+  UNIMPLEMENTED
+
+  *BatteryTag = 0;
+
+  return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+CmBattDisableStatusNotify(PVOID Context)
+{
+  UNIMPLEMENTED
+
+  return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattSetStatusNotify(PVOID Context,
+                      ULONG BatteryTag,
+                      PBATTERY_NOTIFY BatteryNotify)
+{
+  UNIMPLEMENTED
+
+  return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattQueryInformation(PVOID Context,
+                       ULONG BatteryTag,
+                       BATTERY_QUERY_INFORMATION_LEVEL Level,
+                       OPTIONAL LONG AtRate,
+                       PVOID Buffer,
+                       ULONG BufferLength,
+                       PULONG ReturnedLength)
+{
+  UNIMPLEMENTED
+
+  return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattQueryStatus(PVOID Context,
+                  ULONG BatteryTag,
+                  PBATTERY_STATUS BatteryStatus)
+{
+  UNIMPLEMENTED
+
+  return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+CmBattSetInformation(PVOID Context,
+                     ULONG BatteryTag,
+                     BATTERY_SET_INFORMATION_LEVEL Level,
+                     OPTIONAL PVOID Buffer)
+{
+  UNIMPLEMENTED
+
+  return STATUS_NOT_SUPPORTED;
+}
diff --git a/reactos/drivers/battery/directory.rbuild b/reactos/drivers/battery/directory.rbuild
new file mode 100644 (file)
index 0000000..2da9fe0
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE group SYSTEM "../../tools/rbuild/project.dtd">
+<group xmlns:xi="http://www.w3.org/2001/XInclude">
+<directory name="battc">
+       <xi:include href="battc/battc.rbuild" />
+</directory>
+<directory name="cmbatt">
+       <xi:include href="cmbatt/cmbatt.rbuild" />
+</directory>
+</group>
index 5cc82ca..970810f 100644 (file)
@@ -4,6 +4,9 @@
 <directory name="base">
        <xi:include href="base/directory.rbuild" />
 </directory>
+<directory name="battery">
+       <xi:include href="battery/directory.rbuild" />
+</directory>
 <directory name="bus">
        <xi:include href="bus/directory.rbuild" />
 </directory>
diff --git a/reactos/media/inf/battery.inf b/reactos/media/inf/battery.inf
new file mode 100644 (file)
index 0000000..9ac8d89
--- /dev/null
@@ -0,0 +1,52 @@
+; BATTERY.INF\r
+\r
+[Version]\r
+Signature  = "$Windows NT$"\r
+;Signature  = "$ReactOS$"\r
+LayoutFile = layout.inf\r
+Class      = Battery\r
+ClassGUID  = {72631E54-78A4-11D0-BCF7-00AA00B7B32A}\r
+Provider   = %ReactOS%\r
+DriverVer  = 02/28/2010,1.00\r
+\r
+[DestinationDirs]\r
+DefaultDestDir = 12\r
+\r
+[ClassInstall32.NT]\r
+AddReg = BatteryClass.NT.AddReg\r
+\r
+[BatteryClass.NT.AddReg]\r
+HKR, , ,               0, %BatteryClassName%
+;FIXME: Add icon here\r
+\r
+[Manufacturer]\r
+%GenericMfg% = GenericMfg\r
+\r
+[GenericMfg]
+%ACPI\PNP0C0A.DeviceDesc% = CmBatt,ACPI\PNP0C0A\r
+%ACPI\ACPI0003.DeviceDesc% = CmBatt,ACPI\ACPI0003
+
+[CmBatt]\r
+CopyFiles = CmBatt_CopyFiles
+
+[CmBatt_CopyFiles]
+cmbatt.sys
+battc.sys
+\r
+[CmBatt.Services]\r
+AddService = cmbatt, 0x00000002, CmBatt_Service_Install
+
+[CmBatt_Service_Install]
+ServiceType   = 1\r
+StartType     = 3\r
+ErrorControl  = 1\r
+ServiceBinary = %12%\cmbatt.sys\r
+
+[Strings]\r
+ReactOS = "ReactOS Team"
+BatteryClassName = "Batteries"\r
+\r
+GenericMfg = "(Generic batteries)"
+ACPI\PNP0C0A.DeviceDesc = "ACPI-compliant control method battery"
+ACPI\ACPI0003.DeviceDesc = "AC adapter"
+