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