- Fix a warning
 - Implement some IOCTL_ACPI_EVAL_METHOD handling (no input parameters are supported yet but it should be enough for what cmbatt needs it to do)

svn path=/trunk/; revision=46413
This commit is contained in:
Cameron Gutman 2010-03-24 23:13:51 +00:00
parent 91796fd6b5
commit c289730700
4 changed files with 183 additions and 18 deletions

View file

@ -26,6 +26,7 @@
</directory> </directory>
<file>osl.c</file> <file>osl.c</file>
<file>acpienum.c</file> <file>acpienum.c</file>
<file>eval.c</file>
<file>interface.c</file> <file>interface.c</file>
<file>pnp.c</file> <file>pnp.c</file>
<file>power.c</file> <file>power.c</file>

View file

@ -0,0 +1,142 @@
#include <ntddk.h>
#include <acpi.h>
#include <acpisys.h>
#include <acpi_bus.h>
#include <acpi_drivers.h>
#include <acpiioct.h>
#include <glue.h>
#include <accommon.h>
#include <acobject.h>
#include <actypes.h>
#include <wdmguid.h>
#define NDEBUG
#include <debug.h>
NTSTATUS
NTAPI
Bus_PDO_EvalMethod(PPDO_DEVICE_DATA DeviceData,
PIRP Irp)
{
ULONG Signature;
NTSTATUS Status;
ACPI_OBJECT_LIST *ParamList;
PACPI_EVAL_INPUT_BUFFER EvalInputBuff = Irp->AssociatedIrp.SystemBuffer;
ACPI_BUFFER RetBuff = {ACPI_ALLOCATE_BUFFER, NULL};
PACPI_EVAL_OUTPUT_BUFFER OutputBuf;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
return STATUS_INVALID_PARAMETER;
Signature = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
switch (Signature)
{
case ACPI_EVAL_INPUT_BUFFER_SIGNATURE:
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ACPI_EVAL_INPUT_BUFFER))
return STATUS_INVALID_PARAMETER;
ParamList = NULL;
break;
/* FIXME: Support input parameters */
default:
DPRINT1("Unsupported input buffer signature: %d\n", Signature);
return STATUS_NOT_IMPLEMENTED;
}
Status = AcpiEvaluateObject(DeviceData->AcpiHandle,
(CHAR*)EvalInputBuff->MethodName,
ParamList,
&RetBuff);
if (ACPI_SUCCESS(Status))
{
ACPI_OBJECT *Obj = RetBuff.Pointer;
ULONG ExtraParamLength;
switch (Obj->Type)
{
case ACPI_TYPE_INTEGER:
ExtraParamLength = sizeof(ULONG);
break;
case ACPI_TYPE_STRING:
ExtraParamLength = Obj->String.Length;
break;
case ACPI_TYPE_BUFFER:
ExtraParamLength = Obj->Buffer.Length;
break;
case ACPI_TYPE_PACKAGE:
DPRINT1("ACPI_TYPE_PACKAGE not supported yet!\n");
return STATUS_UNSUCCESSFUL;
default:
ASSERT(FALSE);
return STATUS_UNSUCCESSFUL;
}
/* Enough space for a ULONG is always included */
if (ExtraParamLength >= sizeof(ULONG))
ExtraParamLength -= sizeof(ULONG);
else
ExtraParamLength = 0;
OutputBuf = ExAllocatePool(NonPagedPool, sizeof(ACPI_EVAL_OUTPUT_BUFFER) +
ExtraParamLength);
if (!OutputBuf) return STATUS_INSUFFICIENT_RESOURCES;
OutputBuf->Signature = ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE;
OutputBuf->Length = ExtraParamLength + sizeof(ACPI_METHOD_ARGUMENT);
OutputBuf->Count = 1;
switch (Obj->Type)
{
case ACPI_TYPE_INTEGER:
ACPI_METHOD_SET_ARGUMENT_INTEGER(OutputBuf->Argument, Obj->Integer.Value);
break;
case ACPI_TYPE_STRING:
ACPI_METHOD_SET_ARGUMENT_STRING(OutputBuf->Argument, Obj->String.Pointer);
break;
case ACPI_TYPE_BUFFER:
ACPI_METHOD_SET_ARGUMENT_BUFFER(OutputBuf->Argument, Obj->Buffer.Pointer, Obj->Buffer.Length);
break;
case ACPI_TYPE_PACKAGE:
DPRINT1("ACPI_TYPE_PACKAGE not supported yet!\n");
return STATUS_UNSUCCESSFUL;
default:
ASSERT(FALSE);
return STATUS_UNSUCCESSFUL;
}
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ACPI_EVAL_OUTPUT_BUFFER) +
ExtraParamLength)
{
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, OutputBuf, sizeof(ACPI_EVAL_OUTPUT_BUFFER) +
ExtraParamLength);
Irp->IoStatus.Information = sizeof(ACPI_EVAL_OUTPUT_BUFFER) + ExtraParamLength;
ExFreePool(OutputBuf);
return STATUS_SUCCESS;
}
else
{
ExFreePool(OutputBuf);
return STATUS_BUFFER_TOO_SMALL;
}
}
else
{
DPRINT1("Query method %s failed on %p\n", EvalInputBuff->MethodName, DeviceData->AcpiHandle);
return STATUS_UNSUCCESSFUL;
}
}

View file

@ -90,6 +90,11 @@ NTSTATUS
ACPIEnumerateDevices( ACPIEnumerateDevices(
PFDO_DEVICE_DATA DeviceExtension); PFDO_DEVICE_DATA DeviceExtension);
NTSTATUS
NTAPI
Bus_PDO_EvalMethod(PPDO_DEVICE_DATA DeviceData,
PIRP Irp);
NTSTATUS NTSTATUS
NTAPI NTAPI
Bus_CreateClose ( Bus_CreateClose (

View file

@ -6,6 +6,8 @@
#include <acpi_bus.h> #include <acpi_bus.h>
#include <acpi_drivers.h> #include <acpi_drivers.h>
#include <acpiioct.h>
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
@ -29,7 +31,9 @@ Bus_AddDevice(
PDEVICE_OBJECT deviceObject = NULL; PDEVICE_OBJECT deviceObject = NULL;
PFDO_DEVICE_DATA deviceData = NULL; PFDO_DEVICE_DATA deviceData = NULL;
PWCHAR deviceName = NULL; PWCHAR deviceName = NULL;
#ifndef NDEBUG
ULONG nameLength; ULONG nameLength;
#endif
PAGED_CODE (); PAGED_CODE ();
@ -168,32 +172,45 @@ ACPIDispatchDeviceControl(
IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp) IN PIRP Irp)
{ {
PIO_STACK_LOCATION IrpSp; PIO_STACK_LOCATION irpStack;
NTSTATUS Status; NTSTATUS status = STATUS_NOT_SUPPORTED;
PCOMMON_DEVICE_DATA commonData;
DPRINT("Called. IRP is at (0x%X)\n", Irp); PAGED_CODE ();
irpStack = IoGetCurrentIrpStackLocation (Irp);
ASSERT (IRP_MJ_DEVICE_CONTROL == irpStack->MajorFunction);
commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
IrpSp = IoGetCurrentIrpStackLocation(Irp); if (!commonData->IsFDO)
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) { {
default: switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
DPRINT("Unknown IOCTL 0x%X\n", IrpSp->Parameters.DeviceIoControl.IoControlCode); {
Status = STATUS_NOT_IMPLEMENTED; case IOCTL_ACPI_EVAL_METHOD:
break; status = Bus_PDO_EvalMethod((PPDO_DEVICE_DATA)commonData,
} Irp);
break;
if (Status != STATUS_PENDING) { /* TODO: Implement other IOCTLs */
Irp->IoStatus.Status = Status;
DPRINT("Completing IRP at 0x%X\n", Irp); default:
DPRINT1("Unsupported IOCTL: %x\n", irpStack->Parameters.DeviceIoControl.IoControlCode);
break;
}
}
else
DPRINT1("IOCTL sent to the ACPI FDO! Kill the caller!\n");
IoCompleteRequest(Irp, IO_NO_INCREMENT); if (status != STATUS_PENDING)
} {
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
DPRINT("Leaving. Status 0x%X\n", Status); return status;
return Status;
} }
NTSTATUS NTSTATUS