Code cleanup:
[reactos.git] / reactos / drivers / usb / miniport / common / fdo.c
1 /*
2 * PROJECT: ReactOS USB miniport driver (Cromwell type)
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/miniport/common/fdo.c
5 * PURPOSE: Operations on FDOs
6 * PROGRAMMERS: Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
7 * Copyright James Tabor (jimtabor@adsl-64-217-116-74.dsl.hstntx.swbell.net)
8 */
9
10 #define NDEBUG
11 #include <debug.h>
12
13 #include "usbcommon.h"
14
15 #define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
16
17 static VOID
18 UsbMpGetUserBuffers(
19 IN PIRP Irp,
20 IN ULONG IoControlCode,
21 OUT PVOID* BufferIn,
22 OUT PVOID* BufferOut)
23 {
24 ASSERT(Irp);
25 ASSERT(BufferIn);
26 ASSERT(BufferOut);
27
28 switch (IO_METHOD_FROM_CTL_CODE(IoControlCode))
29 {
30 case METHOD_BUFFERED:
31 *BufferIn = *BufferOut = Irp->AssociatedIrp.SystemBuffer;
32 break;
33 case METHOD_IN_DIRECT:
34 case METHOD_OUT_DIRECT:
35 *BufferIn = Irp->AssociatedIrp.SystemBuffer;
36 *BufferOut = MmGetSystemAddressForMdl(Irp->MdlAddress);
37 break;
38 case METHOD_NEITHER:
39 *BufferIn = IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.Type3InputBuffer;
40 *BufferOut = Irp->UserBuffer;
41 break;
42 default:
43 /* Should never happen */
44 *BufferIn = NULL;
45 *BufferOut = NULL;
46 break;
47 }
48 }
49
50 NTSTATUS
51 UsbMpFdoCreate(
52 IN PDEVICE_OBJECT DeviceObject,
53 IN PIRP Irp)
54 {
55 PIO_STACK_LOCATION Stack;
56 PUSBMP_DEVICE_EXTENSION DeviceExtension;
57 NTSTATUS Status;
58
59 DPRINT("IRP_MJ_CREATE\n");
60 Stack = IoGetCurrentIrpStackLocation(Irp);
61 DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
62
63 if (Stack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
64 {
65 CHECKPOINT;
66 Status = STATUS_NOT_A_DIRECTORY;
67 goto ByeBye;
68 }
69
70 InterlockedIncrement((PLONG)&DeviceExtension->DeviceOpened);
71 Status = STATUS_SUCCESS;
72
73 ByeBye:
74 Irp->IoStatus.Status = Status;
75 Irp->IoStatus.Information = 0;
76 IoCompleteRequest(Irp, IO_NO_INCREMENT);
77 return Status;
78 }
79
80 NTSTATUS
81 UsbMpFdoClose(
82 IN PDEVICE_OBJECT DeviceObject,
83 IN PIRP Irp)
84 {
85 PUSBMP_DEVICE_EXTENSION pDeviceExtension;
86
87 DPRINT("IRP_MJ_CLOSE\n");
88 pDeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
89 InterlockedDecrement((PLONG)&pDeviceExtension->DeviceOpened);
90
91 Irp->IoStatus.Information = 0;
92 Irp->IoStatus.Status = STATUS_SUCCESS;
93 IoCompleteRequest(Irp, IO_NO_INCREMENT);
94 return STATUS_SUCCESS;
95 }
96
97 NTSTATUS
98 UsbMpFdoCleanup(
99 IN PDEVICE_OBJECT DeviceObject,
100 IN PIRP Irp)
101 {
102 DPRINT("IRP_MJ_CLEANUP\n");
103
104 Irp->IoStatus.Information = 0;
105 Irp->IoStatus.Status = STATUS_SUCCESS;
106 IoCompleteRequest(Irp, IO_NO_INCREMENT);
107 return STATUS_SUCCESS;
108 }
109
110 static NTSTATUS
111 UsbMpFdoStartDevice(
112 IN PDEVICE_OBJECT DeviceObject,
113 IN PIRP Irp)
114 {
115 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
116 PDRIVER_OBJECT DriverObject;
117 PUSBMP_DRIVER_EXTENSION DriverExtension;
118 PUSBMP_DEVICE_EXTENSION DeviceExtension;
119 PCM_RESOURCE_LIST AllocatedResources;
120 ULONG Size;
121 NTSTATUS Status;
122
123 if (DeviceObject == KeyboardFdo || DeviceObject == MouseFdo)
124 return STATUS_SUCCESS;
125
126 /*
127 * Get the initialization data we saved in VideoPortInitialize.
128 */
129 DriverObject = DeviceObject->DriverObject;
130 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
131 DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
132
133 /*
134 * Store some resources in the DeviceExtension.
135 */
136 AllocatedResources = Stack->Parameters.StartDevice.AllocatedResources;
137 if (AllocatedResources != NULL)
138 {
139 CM_FULL_RESOURCE_DESCRIPTOR *FullList;
140 CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
141 ULONG ResourceCount;
142 ULONG ResourceListSize;
143
144 /* Save the resource list */
145 ResourceCount = AllocatedResources->List[0].PartialResourceList.Count;
146
147 ResourceListSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
148 PartialDescriptors[ResourceCount]);
149
150 DeviceExtension->AllocatedResources = ExAllocatePool(PagedPool, ResourceListSize);
151 if (DeviceExtension->AllocatedResources == NULL)
152 {
153 return STATUS_INSUFFICIENT_RESOURCES;
154 }
155
156 RtlCopyMemory(DeviceExtension->AllocatedResources,
157 AllocatedResources,
158 ResourceListSize);
159
160 /* Get the interrupt level/vector - needed by HwFindAdapter sometimes */
161 for (FullList = AllocatedResources->List;
162 FullList < AllocatedResources->List + AllocatedResources->Count;
163 FullList++)
164 {
165 /* FIXME: Is this ASSERT ok for resources from the PNP manager? */
166 /*ASSERT(FullList->InterfaceType == PCIBus &&
167 FullList->BusNumber == DeviceExtension->SystemIoBusNumber &&
168 1 == FullList->PartialResourceList.Version &&
169 1 == FullList->PartialResourceList.Revision);*/
170 for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
171 Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
172 Descriptor++)
173 {
174 if (Descriptor->Type == CmResourceTypeInterrupt)
175 {
176 DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
177 DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
178 }
179 else if (Descriptor->Type == CmResourceTypePort)
180 {
181 DeviceExtension->BaseAddress = Descriptor->u.Port.Start;
182 DeviceExtension->BaseAddrLength = Descriptor->u.Port.Length;
183 DeviceExtension->Flags = Descriptor->Flags;
184
185 ((struct hc_driver *)pci_ids->driver_data)->flags &= ~HCD_MEMORY;
186 }
187 else if (Descriptor->Type == CmResourceTypeMemory)
188 {
189 DeviceExtension->BaseAddress = Descriptor->u.Memory.Start;
190 DeviceExtension->BaseAddrLength = Descriptor->u.Memory.Length;
191 DeviceExtension->Flags = Descriptor->Flags;
192
193 ((struct hc_driver *)pci_ids->driver_data)->flags |= HCD_MEMORY;
194 }
195 }
196 }
197 }
198
199 /* Print assigned resources */
200 DPRINT("Interrupt Vector 0x%lx, %S base 0x%lx, Length 0x%lx\n",
201 DeviceExtension->InterruptVector,
202 ((struct hc_driver *)pci_ids->driver_data)->flags & HCD_MEMORY ? L"Memory" : L"I/O",
203 DeviceExtension->BaseAddress,
204 DeviceExtension->BaseAddrLength);
205
206 /* Get bus number from the upper level bus driver. */
207 Size = sizeof(ULONG);
208 Status = IoGetDeviceProperty(
209 DeviceExtension->PhysicalDeviceObject,
210 DevicePropertyBusNumber,
211 Size,
212 &DeviceExtension->SystemIoBusNumber,
213 &Size);
214
215 if (!NT_SUCCESS(Status))
216 {
217 DPRINT1("IoGetDeviceProperty DevicePropertyBusNumber failed\n");
218 DeviceExtension->SystemIoBusNumber = 0;
219 }
220
221 DPRINT("Busnumber %d\n", DeviceExtension->SystemIoBusNumber);
222
223 /* Init wrapper with this object */
224 return InitLinuxWrapper(DeviceObject);
225 }
226
227 static NTSTATUS
228 UsbMpFdoQueryBusRelations(
229 IN PDEVICE_OBJECT DeviceObject,
230 OUT PDEVICE_RELATIONS* pDeviceRelations)
231 {
232 PUSBMP_DEVICE_EXTENSION DeviceExtension;
233 PDEVICE_RELATIONS DeviceRelations;
234 NTSTATUS Status = STATUS_SUCCESS;
235
236 DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
237
238 /* Handling this IRP is easy, as we only
239 * have one child: the root hub
240 */
241 DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(
242 PagedPool,
243 sizeof(DEVICE_RELATIONS));
244 if (!DeviceRelations)
245 return STATUS_INSUFFICIENT_RESOURCES;
246
247 /* Fill returned structure */
248 DeviceRelations->Count = 1;
249 ObReferenceObject(DeviceExtension->RootHubPdo);
250 DeviceRelations->Objects[0] = DeviceExtension->RootHubPdo;
251
252 *pDeviceRelations = DeviceRelations;
253 return Status;
254 }
255
256 NTSTATUS
257 UsbMpFdoPnp(
258 IN PDEVICE_OBJECT DeviceObject,
259 IN PIRP Irp)
260 {
261 PIO_STACK_LOCATION IrpSp;
262 NTSTATUS Status;
263 ULONG MinorFunction;
264 ULONG_PTR Information = 0;
265
266 IrpSp = IoGetCurrentIrpStackLocation(Irp);
267 MinorFunction = IrpSp->MinorFunction;
268
269 switch (MinorFunction)
270 {
271 case IRP_MN_START_DEVICE: /* 0x00 */
272 {
273 if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->NextDeviceObject != NULL)
274 /* HACK due to the lack of lower device for legacy USB keyboard and mouse */
275 Status = ForwardIrpAndWait(DeviceObject, Irp);
276 else
277 Status = STATUS_SUCCESS;
278 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
279 Status = UsbMpFdoStartDevice(DeviceObject, Irp);
280 break;
281 }
282
283 case IRP_MN_QUERY_REMOVE_DEVICE: /* 0x01 */
284 case IRP_MN_CANCEL_REMOVE_DEVICE: /* 0x03 */
285 {
286 return ForwardIrpAndForget(DeviceObject, Irp);
287 }
288
289 case IRP_MN_REMOVE_DEVICE: /* 0x02 */
290 case IRP_MN_STOP_DEVICE: /* 0x04 */
291 case IRP_MN_SURPRISE_REMOVAL: /* 0x17 */
292 {
293 if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->NextDeviceObject != NULL)
294 /* HACK due to the lack of lower device for legacy USB keyboard and mouse */
295 Status = ForwardIrpAndWait(DeviceObject, Irp);
296 else
297 Status = STATUS_SUCCESS;
298 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
299 Status = STATUS_SUCCESS;
300 IoDeleteDevice(DeviceObject); // just delete device for now
301 break;
302 }
303
304 case IRP_MN_QUERY_STOP_DEVICE: /* 0x05 */
305 case IRP_MN_CANCEL_STOP_DEVICE: /* 0x06 */
306 {
307 Status = STATUS_SUCCESS;
308 break;
309 }
310 case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x7 */
311 {
312 switch (IrpSp->Parameters.QueryDeviceRelations.Type)
313 {
314 case BusRelations:
315 {
316 PDEVICE_RELATIONS DeviceRelations = NULL;
317 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
318 Status = UsbMpFdoQueryBusRelations(DeviceObject, &DeviceRelations);
319 Information = (ULONG_PTR)DeviceRelations;
320 break;
321 }
322 case RemovalRelations:
323 {
324 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
325 return ForwardIrpAndForget(DeviceObject, Irp);
326 }
327 default:
328 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
329 IrpSp->Parameters.QueryDeviceRelations.Type);
330 return ForwardIrpAndForget(DeviceObject, Irp);
331 }
332 break;
333 }
334
335 default:
336 {
337 DPRINT1("IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
338 return ForwardIrpAndForget(DeviceObject, Irp);
339 }
340 }
341 Irp->IoStatus.Information = Information;
342 Irp->IoStatus.Status = Status;
343 IoCompleteRequest(Irp, IO_NO_INCREMENT);
344 return Status;
345 }
346
347 NTSTATUS
348 UsbMpFdoDeviceControl(
349 IN PDEVICE_OBJECT DeviceObject,
350 IN PIRP Irp)
351 {
352 PIO_STACK_LOCATION Stack;
353 ULONG IoControlCode;
354 PUSBMP_DEVICE_EXTENSION DeviceExtension;
355 ULONG LengthIn, LengthOut;
356 ULONG_PTR Information = 0;
357 PVOID BufferIn, BufferOut;
358 NTSTATUS Status;
359
360 DPRINT("UsbDeviceControlFdo() called\n");
361
362 Stack = IoGetCurrentIrpStackLocation(Irp);
363 LengthIn = Stack->Parameters.DeviceIoControl.InputBufferLength;
364 LengthOut = Stack->Parameters.DeviceIoControl.OutputBufferLength;
365 DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
366 IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode;
367 UsbMpGetUserBuffers(Irp, IoControlCode, &BufferIn, &BufferOut);
368
369 switch (IoControlCode)
370 {
371 case IOCTL_GET_HCD_DRIVERKEY_NAME:
372 {
373 DPRINT("IOCTL_GET_HCD_DRIVERKEY_NAME\n");
374 if (LengthOut < sizeof(USB_HCD_DRIVERKEY_NAME))
375 Status = STATUS_BUFFER_TOO_SMALL;
376 else if (BufferOut == NULL)
377 Status = STATUS_INVALID_PARAMETER;
378 else
379 {
380 PUSB_HCD_DRIVERKEY_NAME StringDescriptor;
381 ULONG StringSize;
382 StringDescriptor = (PUSB_HCD_DRIVERKEY_NAME)BufferOut;
383 Status = IoGetDeviceProperty(
384 ((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->PhysicalDeviceObject,
385 DevicePropertyDriverKeyName,
386 LengthOut - FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName),
387 StringDescriptor->DriverKeyName,
388 &StringSize);
389 if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL)
390 {
391 StringDescriptor->ActualLength = StringSize + FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName);
392 Information = LengthOut;
393 Status = STATUS_SUCCESS;
394 }
395 }
396 break;
397 }
398 case IOCTL_USB_GET_ROOT_HUB_NAME:
399 {
400 DPRINT("IOCTL_USB_GET_ROOT_HUB_NAME\n");
401 if (LengthOut < sizeof(USB_ROOT_HUB_NAME))
402 Status = STATUS_BUFFER_TOO_SMALL;
403 else if (BufferOut == NULL)
404 Status = STATUS_INVALID_PARAMETER;
405 else
406 {
407 PUSB_ROOT_HUB_NAME StringDescriptor;
408 PUNICODE_STRING RootHubInterfaceName;
409 StringDescriptor = (PUSB_ROOT_HUB_NAME)BufferOut;
410 DeviceObject = ((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->RootHubPdo;
411 RootHubInterfaceName = &((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->HcdInterfaceName;
412
413 StringDescriptor->ActualLength = RootHubInterfaceName->Length + sizeof(WCHAR) + FIELD_OFFSET(USB_ROOT_HUB_NAME, RootHubName);
414 if (StringDescriptor->ActualLength <= LengthOut)
415 {
416 /* Copy root hub name */
417 RtlCopyMemory(
418 StringDescriptor->RootHubName,
419 RootHubInterfaceName->Buffer,
420 RootHubInterfaceName->Length);
421 StringDescriptor->RootHubName[RootHubInterfaceName->Length / sizeof(WCHAR)] = UNICODE_NULL;
422 DPRINT("IOCTL_USB_GET_ROOT_HUB_NAME returns '%S'\n", StringDescriptor->RootHubName);
423 Information = StringDescriptor->ActualLength;
424 }
425 else
426 Information = sizeof(USB_ROOT_HUB_NAME);
427 Status = STATUS_SUCCESS;
428 }
429 break;
430 }
431
432 default:
433 {
434 /* Pass Irp to lower driver */
435 DPRINT1("Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode);
436 IoSkipCurrentIrpStackLocation(Irp);
437 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
438 }
439 }
440
441 Irp->IoStatus.Information = Information;
442 Irp->IoStatus.Status = Status;
443 IoCompleteRequest(Irp, IO_NO_INCREMENT);
444 return Status;
445 }