7 #include <acpi_drivers.h>
16 #pragma alloc_text (INIT, DriverEntry)
17 #pragma alloc_text (PAGE, Bus_AddDevice)
21 extern struct acpi_device
*sleep_button
;
22 extern struct acpi_device
*power_button
;
27 PDRIVER_OBJECT DriverObject
,
28 PDEVICE_OBJECT PhysicalDeviceObject
33 PDEVICE_OBJECT deviceObject
= NULL
;
34 PFDO_DEVICE_DATA deviceData
= NULL
;
35 PWCHAR deviceName
= NULL
;
42 DPRINT("Add Device: 0x%p\n", PhysicalDeviceObject
);
44 DPRINT("#################### Bus_CreateClose Creating FDO Device ####################\n");
45 status
= IoCreateDevice(DriverObject
,
46 sizeof(FDO_DEVICE_DATA
),
49 FILE_DEVICE_SECURE_OPEN
,
52 if (!NT_SUCCESS(status
))
54 DPRINT1("IoCreateDevice() failed with status 0x%X\n", status
);
58 deviceData
= (PFDO_DEVICE_DATA
) deviceObject
->DeviceExtension
;
59 RtlZeroMemory (deviceData
, sizeof (FDO_DEVICE_DATA
));
62 // Set the initial state of the FDO
65 INITIALIZE_PNP_STATE(deviceData
->Common
);
67 deviceData
->Common
.IsFDO
= TRUE
;
69 deviceData
->Common
.Self
= deviceObject
;
71 ExInitializeFastMutex (&deviceData
->Mutex
);
73 InitializeListHead (&deviceData
->ListOfPDOs
);
75 // Set the PDO for use with PlugPlay functions
77 deviceData
->UnderlyingPDO
= PhysicalDeviceObject
;
80 // Set the initial powerstate of the FDO
83 deviceData
->Common
.DevicePowerState
= PowerDeviceUnspecified
;
84 deviceData
->Common
.SystemPowerState
= PowerSystemWorking
;
86 deviceObject
->Flags
|= DO_POWER_PAGABLE
;
89 // Attach our FDO to the device stack.
90 // The return value of IoAttachDeviceToDeviceStack is the top of the
91 // attachment chain. This is where all the IRPs should be routed.
94 deviceData
->NextLowerDriver
= IoAttachDeviceToDeviceStack (
96 PhysicalDeviceObject
);
98 if (NULL
== deviceData
->NextLowerDriver
) {
100 status
= STATUS_NO_SUCH_DEVICE
;
107 // We will demonstrate here the step to retrieve the name of the PDO
110 status
= IoGetDeviceProperty (PhysicalDeviceObject
,
111 DevicePropertyPhysicalDeviceObjectName
,
116 if (status
!= STATUS_BUFFER_TOO_SMALL
)
118 DPRINT1("AddDevice:IoGDP failed (0x%x)\n", status
);
122 deviceName
= ExAllocatePoolWithTag (NonPagedPool
,
125 if (NULL
== deviceName
) {
126 DPRINT1("AddDevice: no memory to alloc for deviceName(0x%x)\n", nameLength
);
127 status
= STATUS_INSUFFICIENT_RESOURCES
;
131 status
= IoGetDeviceProperty (PhysicalDeviceObject
,
132 DevicePropertyPhysicalDeviceObjectName
,
137 if (!NT_SUCCESS (status
)) {
139 DPRINT1("AddDevice:IoGDP(2) failed (0x%x)", status
);
143 DPRINT("AddDevice: %p to %p->%p (%ws) \n",
145 deviceData
->NextLowerDriver
,
146 PhysicalDeviceObject
,
152 // We are done with initializing, so let's indicate that and return.
153 // This should be the final step in the AddDevice process.
155 deviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
159 ExFreePool(deviceName
);
161 if (!NT_SUCCESS(status
) && deviceObject
){
162 if (deviceData
&& deviceData
->NextLowerDriver
){
163 IoDetachDevice (deviceData
->NextLowerDriver
);
165 IoDeleteDevice (deviceObject
);
173 ACPIDispatchCreateClose(
174 IN PDEVICE_OBJECT DeviceObject
,
177 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
178 Irp
->IoStatus
.Information
= 0;
180 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
182 return STATUS_SUCCESS
;
187 ACPIDispatchDeviceControl(
188 IN PDEVICE_OBJECT DeviceObject
,
191 PIO_STACK_LOCATION irpStack
;
192 NTSTATUS status
= STATUS_NOT_SUPPORTED
;
193 PCOMMON_DEVICE_DATA commonData
;
198 irpStack
= IoGetCurrentIrpStackLocation (Irp
);
199 ASSERT (IRP_MJ_DEVICE_CONTROL
== irpStack
->MajorFunction
);
201 commonData
= (PCOMMON_DEVICE_DATA
) DeviceObject
->DeviceExtension
;
203 Irp
->IoStatus
.Information
= 0;
205 if (!commonData
->IsFDO
)
207 switch (irpStack
->Parameters
.DeviceIoControl
.IoControlCode
)
209 case IOCTL_ACPI_EVAL_METHOD
:
210 status
= Bus_PDO_EvalMethod((PPDO_DEVICE_DATA
)commonData
,
214 case IOCTL_GET_SYS_BUTTON_CAPS
:
215 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(ULONG
))
217 status
= STATUS_BUFFER_TOO_SMALL
;
221 if (wcsstr(((PPDO_DEVICE_DATA
)commonData
)->HardwareIDs
, L
"PNP0C0D"))
223 DPRINT1("Lid button reported to power manager\n");
224 Caps
|= SYS_BUTTON_LID
;
226 else if (((PPDO_DEVICE_DATA
)commonData
)->AcpiHandle
== NULL
)
228 /* We have to return both at the same time because since we
229 * have a NULL handle we are the fixed feature DO and we will
230 * only be called once (not once per device)
234 DPRINT1("Fixed power button reported to power manager\n");
235 Caps
|= SYS_BUTTON_POWER
;
239 DPRINT1("Fixed sleep button reported to power manager\n");
240 Caps
|= SYS_BUTTON_SLEEP
;
243 if (wcsstr(((PPDO_DEVICE_DATA
)commonData
)->HardwareIDs
, L
"PNP0C0C"))
245 DPRINT1("Control method power button reported to power manager\n");
246 Caps
|= SYS_BUTTON_POWER
;
248 else if (wcsstr(((PPDO_DEVICE_DATA
)commonData
)->HardwareIDs
, L
"PNP0C0E"))
250 DPRINT1("Control method sleep reported to power manager\n");
251 Caps
|= SYS_BUTTON_SLEEP
;
255 DPRINT1("IOCTL_GET_SYS_BUTTON_CAPS sent to a non-button device\n");
256 status
= STATUS_INVALID_PARAMETER
;
261 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, &Caps
, sizeof(Caps
));
262 Irp
->IoStatus
.Information
= sizeof(Caps
);
263 status
= STATUS_SUCCESS
;
267 /* TODO: Implement other IOCTLs */
270 DPRINT1("Unsupported IOCTL: %x\n", irpStack
->Parameters
.DeviceIoControl
.IoControlCode
);
275 DPRINT1("IOCTL sent to the ACPI FDO! Kill the caller!\n");
277 if (status
!= STATUS_PENDING
)
279 Irp
->IoStatus
.Status
= status
;
280 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
289 PDRIVER_OBJECT DriverObject
,
290 PUNICODE_STRING RegistryPath
293 DPRINT("Driver Entry \n");
296 // Set entry points into the driver
298 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ACPIDispatchDeviceControl
;
299 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = Bus_PnP
;
300 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = Bus_Power
;
301 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ACPIDispatchCreateClose
;
302 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ACPIDispatchCreateClose
;
304 DriverObject
->DriverExtension
->AddDevice
= Bus_AddDevice
;
306 return STATUS_SUCCESS
;