X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=drivers%2Fbus%2Facpi%2Fmain.c;h=175ad53d72887a744302d82b0ba50ac34fc93fa3;hp=3d1170eefd6d2f4d38a7283bad1d4f310496302c;hb=b6edb50eb1a2311af040aadeec7791efa270a72e;hpb=76085ba9824b9b4ac80dc6af201e47ce88df585c diff --git a/drivers/bus/acpi/main.c b/drivers/bus/acpi/main.c index 3d1170eefd6..175ad53d728 100644 --- a/drivers/bus/acpi/main.c +++ b/drivers/bus/acpi/main.c @@ -6,6 +6,9 @@ #include #include +#include +#include + #define NDEBUG #include @@ -15,7 +18,8 @@ #endif - +extern struct acpi_device *sleep_button; +extern struct acpi_device *power_button; NTSTATUS NTAPI @@ -29,7 +33,9 @@ Bus_AddDevice( PDEVICE_OBJECT deviceObject = NULL; PFDO_DEVICE_DATA deviceData = NULL; PWCHAR deviceName = NULL; +#ifndef NDEBUG ULONG nameLength; +#endif PAGED_CODE (); @@ -164,36 +170,159 @@ End: NTSTATUS NTAPI -ACPIDispatchDeviceControl( +ACPIDispatchCreateClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - PIO_STACK_LOCATION IrpSp; - NTSTATUS Status; + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; - DPRINT("Called. IRP is at (0x%X)\n", Irp); + IoCompleteRequest(Irp, IO_NO_INCREMENT); - Irp->IoStatus.Information = 0; + return STATUS_SUCCESS; +} - IrpSp = IoGetCurrentIrpStackLocation(Irp); - switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) { - default: - DPRINT("Unknown IOCTL 0x%X\n", IrpSp->Parameters.DeviceIoControl.IoControlCode); - Status = STATUS_NOT_IMPLEMENTED; - break; - } +VOID +NTAPI +ButtonWaitThread(PVOID Context) +{ + PIRP Irp = Context; + int result; + struct acpi_bus_event event; + ULONG ButtonEvent; - if (Status != STATUS_PENDING) { - Irp->IoStatus.Status = Status; + while (ACPI_SUCCESS(result = acpi_bus_receive_event(&event)) && + event.type != ACPI_BUTTON_NOTIFY_STATUS); - DPRINT("Completing IRP at 0x%X\n", Irp); + if (!ACPI_SUCCESS(result)) + { + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + } + else + { + if (strstr(event.bus_id, "PWRF")) + ButtonEvent = SYS_BUTTON_POWER; + else if (strstr(event.bus_id, "SLPF")) + ButtonEvent = SYS_BUTTON_SLEEP; + else + ButtonEvent = 0; + + RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, &ButtonEvent, sizeof(ButtonEvent)); + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof(ULONG); + } - IoCompleteRequest(Irp, IO_NO_INCREMENT); - } + IoCompleteRequest(Irp, IO_NO_INCREMENT); +} + - DPRINT("Leaving. Status 0x%X\n", Status); +NTSTATUS +NTAPI +ACPIDispatchDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION irpStack; + NTSTATUS status = STATUS_NOT_SUPPORTED; + PCOMMON_DEVICE_DATA commonData; + ULONG Caps = 0; + HANDLE ThreadHandle; + + PAGED_CODE (); + + irpStack = IoGetCurrentIrpStackLocation (Irp); + ASSERT (IRP_MJ_DEVICE_CONTROL == irpStack->MajorFunction); + + commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension; + + Irp->IoStatus.Information = 0; + + if (!commonData->IsFDO) + { + switch (irpStack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_ACPI_EVAL_METHOD: + status = Bus_PDO_EvalMethod((PPDO_DEVICE_DATA)commonData, + Irp); + break; + + case IOCTL_GET_SYS_BUTTON_CAPS: + if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)) + { + status = STATUS_BUFFER_TOO_SMALL; + break; + } + + if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0D")) + { + DPRINT1("Lid button reported to power manager\n"); + Caps |= SYS_BUTTON_LID; + } + else if (((PPDO_DEVICE_DATA)commonData)->AcpiHandle == NULL) + { + /* We have to return both at the same time because since we + * have a NULL handle we are the fixed feature DO and we will + * only be called once (not once per device) + */ + if (power_button) + { + DPRINT1("Fixed power button reported to power manager\n"); + Caps |= SYS_BUTTON_POWER; + } + if (sleep_button) + { + DPRINT1("Fixed sleep button reported to power manager\n"); + Caps |= SYS_BUTTON_SLEEP; + } + } + else if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0C")) + { + DPRINT1("Control method power button reported to power manager\n"); + Caps |= SYS_BUTTON_POWER; + } + else if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0E")) + { + DPRINT1("Control method sleep reported to power manager\n"); + Caps |= SYS_BUTTON_SLEEP; + } + else + { + DPRINT1("IOCTL_GET_SYS_BUTTON_CAPS sent to a non-button device\n"); + status = STATUS_INVALID_PARAMETER; + } + + if (Caps != 0) + { + RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, &Caps, sizeof(Caps)); + Irp->IoStatus.Information = sizeof(Caps); + status = STATUS_SUCCESS; + } + break; + + case IOCTL_GET_SYS_BUTTON_EVENT: + PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0, ButtonWaitThread, Irp); + ZwClose(ThreadHandle); + + status = STATUS_PENDING; + break; + + default: + DPRINT1("Unsupported IOCTL: %x\n", irpStack->Parameters.DeviceIoControl.IoControlCode); + break; + } + } + else + DPRINT1("IOCTL sent to the ACPI FDO! Kill the caller!\n"); - return Status; + if (status != STATUS_PENDING) + { + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + else + IoMarkIrpPending(Irp); + + return status; } NTSTATUS @@ -211,6 +340,8 @@ DriverEntry ( DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ACPIDispatchDeviceControl; DriverObject->MajorFunction [IRP_MJ_PNP] = Bus_PnP; DriverObject->MajorFunction [IRP_MJ_POWER] = Bus_Power; + DriverObject->MajorFunction [IRP_MJ_CREATE] = ACPIDispatchCreateClose; + DriverObject->MajorFunction [IRP_MJ_CLOSE] = ACPIDispatchCreateClose; DriverObject->DriverExtension->AddDevice = Bus_AddDevice;