7 #include <acpi_drivers.h>
18 PDRIVER_OBJECT DriverObject
,
19 PUNICODE_STRING RegistryPath
23 #pragma alloc_text (INIT, DriverEntry)
24 #pragma alloc_text (PAGE, Bus_AddDevice)
28 extern struct acpi_device
*sleep_button
;
29 extern struct acpi_device
*power_button
;
34 PDRIVER_OBJECT DriverObject
,
35 PDEVICE_OBJECT PhysicalDeviceObject
40 PDEVICE_OBJECT deviceObject
= NULL
;
41 PFDO_DEVICE_DATA deviceData
= NULL
;
42 PWCHAR deviceName
= NULL
;
49 DPRINT("Add Device: 0x%p\n", PhysicalDeviceObject
);
51 DPRINT("#################### Bus_CreateClose Creating FDO Device ####################\n");
52 status
= IoCreateDevice(DriverObject
,
53 sizeof(FDO_DEVICE_DATA
),
56 FILE_DEVICE_SECURE_OPEN
,
59 if (!NT_SUCCESS(status
))
61 DPRINT1("IoCreateDevice() failed with status 0x%X\n", status
);
65 deviceData
= (PFDO_DEVICE_DATA
) deviceObject
->DeviceExtension
;
66 RtlZeroMemory (deviceData
, sizeof (FDO_DEVICE_DATA
));
69 // Set the initial state of the FDO
72 INITIALIZE_PNP_STATE(deviceData
->Common
);
74 deviceData
->Common
.IsFDO
= TRUE
;
76 deviceData
->Common
.Self
= deviceObject
;
78 ExInitializeFastMutex (&deviceData
->Mutex
);
80 InitializeListHead (&deviceData
->ListOfPDOs
);
82 // Set the PDO for use with PlugPlay functions
84 deviceData
->UnderlyingPDO
= PhysicalDeviceObject
;
87 // Set the initial powerstate of the FDO
90 deviceData
->Common
.DevicePowerState
= PowerDeviceUnspecified
;
91 deviceData
->Common
.SystemPowerState
= PowerSystemWorking
;
93 deviceObject
->Flags
|= DO_POWER_PAGABLE
;
96 // Attach our FDO to the device stack.
97 // The return value of IoAttachDeviceToDeviceStack is the top of the
98 // attachment chain. This is where all the IRPs should be routed.
101 deviceData
->NextLowerDriver
= IoAttachDeviceToDeviceStack (
103 PhysicalDeviceObject
);
105 if (NULL
== deviceData
->NextLowerDriver
) {
107 status
= STATUS_NO_SUCH_DEVICE
;
114 // We will demonstrate here the step to retrieve the name of the PDO
117 status
= IoGetDeviceProperty (PhysicalDeviceObject
,
118 DevicePropertyPhysicalDeviceObjectName
,
123 if (status
!= STATUS_BUFFER_TOO_SMALL
)
125 DPRINT1("AddDevice:IoGDP failed (0x%x)\n", status
);
129 deviceName
= ExAllocatePoolWithTag (NonPagedPool
,
132 if (NULL
== deviceName
) {
133 DPRINT1("AddDevice: no memory to alloc for deviceName(0x%x)\n", nameLength
);
134 status
= STATUS_INSUFFICIENT_RESOURCES
;
138 status
= IoGetDeviceProperty (PhysicalDeviceObject
,
139 DevicePropertyPhysicalDeviceObjectName
,
144 if (!NT_SUCCESS (status
)) {
146 DPRINT1("AddDevice:IoGDP(2) failed (0x%x)", status
);
150 DPRINT("AddDevice: %p to %p->%p (%ws) \n",
152 deviceData
->NextLowerDriver
,
153 PhysicalDeviceObject
,
159 // We are done with initializing, so let's indicate that and return.
160 // This should be the final step in the AddDevice process.
162 deviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
166 ExFreePoolWithTag(deviceName
, 'IPCA');
168 if (!NT_SUCCESS(status
) && deviceObject
){
169 if (deviceData
&& deviceData
->NextLowerDriver
){
170 IoDetachDevice (deviceData
->NextLowerDriver
);
172 IoDeleteDevice (deviceObject
);
180 ACPIDispatchCreateClose(
181 IN PDEVICE_OBJECT DeviceObject
,
184 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
185 Irp
->IoStatus
.Information
= 0;
187 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
189 return STATUS_SUCCESS
;
194 ButtonWaitThread(PVOID Context
)
198 struct acpi_bus_event event
;
201 while (ACPI_SUCCESS(result
= acpi_bus_receive_event(&event
)) &&
202 event
.type
!= ACPI_BUTTON_NOTIFY_STATUS
);
204 if (!ACPI_SUCCESS(result
))
206 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
210 if (strstr(event
.bus_id
, "PWRF"))
211 ButtonEvent
= SYS_BUTTON_POWER
;
212 else if (strstr(event
.bus_id
, "SLPF"))
213 ButtonEvent
= SYS_BUTTON_SLEEP
;
217 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, &ButtonEvent
, sizeof(ButtonEvent
));
218 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
219 Irp
->IoStatus
.Information
= sizeof(ULONG
);
222 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
228 ACPIDispatchDeviceControl(
229 IN PDEVICE_OBJECT DeviceObject
,
232 PIO_STACK_LOCATION irpStack
;
233 NTSTATUS status
= STATUS_NOT_SUPPORTED
;
234 PCOMMON_DEVICE_DATA commonData
;
240 irpStack
= IoGetCurrentIrpStackLocation (Irp
);
241 ASSERT (IRP_MJ_DEVICE_CONTROL
== irpStack
->MajorFunction
);
243 commonData
= (PCOMMON_DEVICE_DATA
) DeviceObject
->DeviceExtension
;
245 Irp
->IoStatus
.Information
= 0;
247 if (!commonData
->IsFDO
)
249 switch (irpStack
->Parameters
.DeviceIoControl
.IoControlCode
)
251 case IOCTL_ACPI_EVAL_METHOD
:
252 status
= Bus_PDO_EvalMethod((PPDO_DEVICE_DATA
)commonData
,
256 case IOCTL_GET_SYS_BUTTON_CAPS
:
257 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(ULONG
))
259 status
= STATUS_BUFFER_TOO_SMALL
;
263 if (wcsstr(((PPDO_DEVICE_DATA
)commonData
)->HardwareIDs
, L
"PNP0C0D"))
265 DPRINT1("Lid button reported to power manager\n");
266 Caps
|= SYS_BUTTON_LID
;
268 else if (((PPDO_DEVICE_DATA
)commonData
)->AcpiHandle
== NULL
)
270 /* We have to return both at the same time because since we
271 * have a NULL handle we are the fixed feature DO and we will
272 * only be called once (not once per device)
276 DPRINT1("Fixed power button reported to power manager\n");
277 Caps
|= SYS_BUTTON_POWER
;
281 DPRINT1("Fixed sleep button reported to power manager\n");
282 Caps
|= SYS_BUTTON_SLEEP
;
285 else if (wcsstr(((PPDO_DEVICE_DATA
)commonData
)->HardwareIDs
, L
"PNP0C0C"))
287 DPRINT1("Control method power button reported to power manager\n");
288 Caps
|= SYS_BUTTON_POWER
;
290 else if (wcsstr(((PPDO_DEVICE_DATA
)commonData
)->HardwareIDs
, L
"PNP0C0E"))
292 DPRINT1("Control method sleep reported to power manager\n");
293 Caps
|= SYS_BUTTON_SLEEP
;
297 DPRINT1("IOCTL_GET_SYS_BUTTON_CAPS sent to a non-button device\n");
298 status
= STATUS_INVALID_PARAMETER
;
303 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, &Caps
, sizeof(Caps
));
304 Irp
->IoStatus
.Information
= sizeof(Caps
);
305 status
= STATUS_SUCCESS
;
309 case IOCTL_GET_SYS_BUTTON_EVENT
:
310 PsCreateSystemThread(&ThreadHandle
, THREAD_ALL_ACCESS
, 0, 0, 0, ButtonWaitThread
, Irp
);
311 ZwClose(ThreadHandle
);
313 status
= STATUS_PENDING
;
317 DPRINT1("Unsupported IOCTL: %x\n", irpStack
->Parameters
.DeviceIoControl
.IoControlCode
);
322 DPRINT1("IOCTL sent to the ACPI FDO! Kill the caller!\n");
324 if (status
!= STATUS_PENDING
)
326 Irp
->IoStatus
.Status
= status
;
327 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
330 IoMarkIrpPending(Irp
);
338 PDRIVER_OBJECT DriverObject
,
339 PUNICODE_STRING RegistryPath
342 DPRINT("Driver Entry \n");
345 // Set entry points into the driver
347 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ACPIDispatchDeviceControl
;
348 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = Bus_PnP
;
349 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = Bus_Power
;
350 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ACPIDispatchCreateClose
;
351 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ACPIDispatchCreateClose
;
353 DriverObject
->DriverExtension
->AddDevice
= Bus_AddDevice
;
355 return STATUS_SUCCESS
;