[ACPI]
[reactos.git] / reactos / drivers / bus / acpi / main.c
1 #include <ntddk.h>
2
3 #include <acpi.h>
4 #include <acpisys.h>
5
6 #include <acpi_bus.h>
7 #include <acpi_drivers.h>
8
9 #include <acpiioct.h>
10 #include <poclass.h>
11
12 #define NDEBUG
13 #include <debug.h>
14
15 #ifdef ALLOC_PRAGMA
16 #pragma alloc_text (INIT, DriverEntry)
17 #pragma alloc_text (PAGE, Bus_AddDevice)
18
19 #endif
20
21 extern struct acpi_device *sleep_button;
22 extern struct acpi_device *power_button;
23
24 NTSTATUS
25 NTAPI
26 Bus_AddDevice(
27 PDRIVER_OBJECT DriverObject,
28 PDEVICE_OBJECT PhysicalDeviceObject
29 )
30
31 {
32 NTSTATUS status;
33 PDEVICE_OBJECT deviceObject = NULL;
34 PFDO_DEVICE_DATA deviceData = NULL;
35 PWCHAR deviceName = NULL;
36 #ifndef NDEBUG
37 ULONG nameLength;
38 #endif
39
40 PAGED_CODE ();
41
42 DPRINT("Add Device: 0x%p\n", PhysicalDeviceObject);
43
44 DPRINT("#################### Bus_CreateClose Creating FDO Device ####################\n");
45 status = IoCreateDevice(DriverObject,
46 sizeof(FDO_DEVICE_DATA),
47 NULL,
48 FILE_DEVICE_ACPI,
49 FILE_DEVICE_SECURE_OPEN,
50 TRUE,
51 &deviceObject);
52 if (!NT_SUCCESS(status))
53 {
54 DPRINT1("IoCreateDevice() failed with status 0x%X\n", status);
55 goto End;
56 }
57
58 deviceData = (PFDO_DEVICE_DATA) deviceObject->DeviceExtension;
59 RtlZeroMemory (deviceData, sizeof (FDO_DEVICE_DATA));
60
61 //
62 // Set the initial state of the FDO
63 //
64
65 INITIALIZE_PNP_STATE(deviceData->Common);
66
67 deviceData->Common.IsFDO = TRUE;
68
69 deviceData->Common.Self = deviceObject;
70
71 ExInitializeFastMutex (&deviceData->Mutex);
72
73 InitializeListHead (&deviceData->ListOfPDOs);
74
75 // Set the PDO for use with PlugPlay functions
76
77 deviceData->UnderlyingPDO = PhysicalDeviceObject;
78
79 //
80 // Set the initial powerstate of the FDO
81 //
82
83 deviceData->Common.DevicePowerState = PowerDeviceUnspecified;
84 deviceData->Common.SystemPowerState = PowerSystemWorking;
85
86 deviceObject->Flags |= DO_POWER_PAGABLE;
87
88 //
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.
92 //
93
94 deviceData->NextLowerDriver = IoAttachDeviceToDeviceStack (
95 deviceObject,
96 PhysicalDeviceObject);
97
98 if (NULL == deviceData->NextLowerDriver) {
99
100 status = STATUS_NO_SUCH_DEVICE;
101 goto End;
102 }
103
104
105 #ifndef NDEBUG
106 //
107 // We will demonstrate here the step to retrieve the name of the PDO
108 //
109
110 status = IoGetDeviceProperty (PhysicalDeviceObject,
111 DevicePropertyPhysicalDeviceObjectName,
112 0,
113 NULL,
114 &nameLength);
115
116 if (status != STATUS_BUFFER_TOO_SMALL)
117 {
118 DPRINT1("AddDevice:IoGDP failed (0x%x)\n", status);
119 goto End;
120 }
121
122 deviceName = ExAllocatePoolWithTag (NonPagedPool,
123 nameLength, 'IPCA');
124
125 if (NULL == deviceName) {
126 DPRINT1("AddDevice: no memory to alloc for deviceName(0x%x)\n", nameLength);
127 status = STATUS_INSUFFICIENT_RESOURCES;
128 goto End;
129 }
130
131 status = IoGetDeviceProperty (PhysicalDeviceObject,
132 DevicePropertyPhysicalDeviceObjectName,
133 nameLength,
134 deviceName,
135 &nameLength);
136
137 if (!NT_SUCCESS (status)) {
138
139 DPRINT1("AddDevice:IoGDP(2) failed (0x%x)", status);
140 goto End;
141 }
142
143 DPRINT("AddDevice: %p to %p->%p (%ws) \n",
144 deviceObject,
145 deviceData->NextLowerDriver,
146 PhysicalDeviceObject,
147 deviceName);
148
149 #endif
150
151 //
152 // We are done with initializing, so let's indicate that and return.
153 // This should be the final step in the AddDevice process.
154 //
155 deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
156
157 End:
158 if (deviceName){
159 ExFreePool(deviceName);
160 }
161 if (!NT_SUCCESS(status) && deviceObject){
162 if (deviceData && deviceData->NextLowerDriver){
163 IoDetachDevice (deviceData->NextLowerDriver);
164 }
165 IoDeleteDevice (deviceObject);
166 }
167 return status;
168
169 }
170
171 NTSTATUS
172 NTAPI
173 ACPIDispatchCreateClose(
174 IN PDEVICE_OBJECT DeviceObject,
175 IN PIRP Irp)
176 {
177 Irp->IoStatus.Status = STATUS_SUCCESS;
178 Irp->IoStatus.Information = 0;
179
180 IoCompleteRequest(Irp, IO_NO_INCREMENT);
181
182 return STATUS_SUCCESS;
183 }
184
185 NTSTATUS
186 NTAPI
187 ACPIDispatchDeviceControl(
188 IN PDEVICE_OBJECT DeviceObject,
189 IN PIRP Irp)
190 {
191 PIO_STACK_LOCATION irpStack;
192 NTSTATUS status = STATUS_NOT_SUPPORTED;
193 PCOMMON_DEVICE_DATA commonData;
194 ULONG Caps = 0;
195
196 PAGED_CODE ();
197
198 irpStack = IoGetCurrentIrpStackLocation (Irp);
199 ASSERT (IRP_MJ_DEVICE_CONTROL == irpStack->MajorFunction);
200
201 commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
202
203 Irp->IoStatus.Information = 0;
204
205 if (!commonData->IsFDO)
206 {
207 switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
208 {
209 case IOCTL_ACPI_EVAL_METHOD:
210 status = Bus_PDO_EvalMethod((PPDO_DEVICE_DATA)commonData,
211 Irp);
212 break;
213
214 case IOCTL_GET_SYS_BUTTON_CAPS:
215 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
216 {
217 status = STATUS_BUFFER_TOO_SMALL;
218 break;
219 }
220
221 if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0D"))
222 {
223 DPRINT1("Lid button reported to power manager\n");
224 Caps |= SYS_BUTTON_LID;
225 }
226 else if (((PPDO_DEVICE_DATA)commonData)->AcpiHandle == NULL)
227 {
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)
231 */
232 if (power_button)
233 {
234 DPRINT1("Fixed power button reported to power manager\n");
235 Caps |= SYS_BUTTON_POWER;
236 }
237 if (sleep_button)
238 {
239 DPRINT1("Fixed sleep button reported to power manager\n");
240 Caps |= SYS_BUTTON_SLEEP;
241 }
242 }
243 if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0C"))
244 {
245 DPRINT1("Control method power button reported to power manager\n");
246 Caps |= SYS_BUTTON_POWER;
247 }
248 else if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0E"))
249 {
250 DPRINT1("Control method sleep reported to power manager\n");
251 Caps |= SYS_BUTTON_SLEEP;
252 }
253 else
254 {
255 DPRINT1("IOCTL_GET_SYS_BUTTON_CAPS sent to a non-button device\n");
256 status = STATUS_INVALID_PARAMETER;
257 }
258
259 if (Caps != 0)
260 {
261 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, &Caps, sizeof(Caps));
262 Irp->IoStatus.Information = sizeof(Caps);
263 status = STATUS_SUCCESS;
264 }
265 break;
266
267 /* TODO: Implement other IOCTLs */
268
269 default:
270 DPRINT1("Unsupported IOCTL: %x\n", irpStack->Parameters.DeviceIoControl.IoControlCode);
271 break;
272 }
273 }
274 else
275 DPRINT1("IOCTL sent to the ACPI FDO! Kill the caller!\n");
276
277 if (status != STATUS_PENDING)
278 {
279 Irp->IoStatus.Status = status;
280 IoCompleteRequest(Irp, IO_NO_INCREMENT);
281 }
282
283 return status;
284 }
285
286 NTSTATUS
287 NTAPI
288 DriverEntry (
289 PDRIVER_OBJECT DriverObject,
290 PUNICODE_STRING RegistryPath
291 )
292 {
293 DPRINT("Driver Entry \n");
294
295 //
296 // Set entry points into the driver
297 //
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;
303
304 DriverObject->DriverExtension->AddDevice = Bus_AddDevice;
305
306 return STATUS_SUCCESS;
307 }