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)
13 #include "usbcommon.h"
15 #define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
20 IN ULONG IoControlCode
,
28 switch (IO_METHOD_FROM_CTL_CODE(IoControlCode
))
31 *BufferIn
= *BufferOut
= Irp
->AssociatedIrp
.SystemBuffer
;
33 case METHOD_IN_DIRECT
:
34 case METHOD_OUT_DIRECT
:
35 *BufferIn
= Irp
->AssociatedIrp
.SystemBuffer
;
36 *BufferOut
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
39 *BufferIn
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.DeviceIoControl
.Type3InputBuffer
;
40 *BufferOut
= Irp
->UserBuffer
;
43 /* Should never happen */
52 IN PDEVICE_OBJECT DeviceObject
,
55 PIO_STACK_LOCATION Stack
;
56 PUSBMP_DEVICE_EXTENSION DeviceExtension
;
59 DPRINT("IRP_MJ_CREATE\n");
60 Stack
= IoGetCurrentIrpStackLocation(Irp
);
61 DeviceExtension
= (PUSBMP_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
63 if (Stack
->Parameters
.Create
.Options
& FILE_DIRECTORY_FILE
)
66 Status
= STATUS_NOT_A_DIRECTORY
;
70 InterlockedIncrement((PLONG
)&DeviceExtension
->DeviceOpened
);
71 Status
= STATUS_SUCCESS
;
74 Irp
->IoStatus
.Status
= Status
;
75 Irp
->IoStatus
.Information
= 0;
76 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
82 IN PDEVICE_OBJECT DeviceObject
,
85 PUSBMP_DEVICE_EXTENSION pDeviceExtension
;
87 DPRINT("IRP_MJ_CLOSE\n");
88 pDeviceExtension
= (PUSBMP_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
89 InterlockedDecrement((PLONG
)&pDeviceExtension
->DeviceOpened
);
91 Irp
->IoStatus
.Information
= 0;
92 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
93 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
94 return STATUS_SUCCESS
;
99 IN PDEVICE_OBJECT DeviceObject
,
102 DPRINT("IRP_MJ_CLEANUP\n");
104 Irp
->IoStatus
.Information
= 0;
105 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
106 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
107 return STATUS_SUCCESS
;
112 IN PDEVICE_OBJECT DeviceObject
,
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
;
123 if (DeviceObject
== KeyboardFdo
|| DeviceObject
== MouseFdo
)
124 return STATUS_SUCCESS
;
127 * Get the initialization data we saved in VideoPortInitialize.
129 DriverObject
= DeviceObject
->DriverObject
;
130 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
131 DeviceExtension
= (PUSBMP_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
134 * Store some resources in the DeviceExtension.
136 AllocatedResources
= Stack
->Parameters
.StartDevice
.AllocatedResources
;
137 if (AllocatedResources
!= NULL
)
139 CM_FULL_RESOURCE_DESCRIPTOR
*FullList
;
140 CM_PARTIAL_RESOURCE_DESCRIPTOR
*Descriptor
;
142 ULONG ResourceListSize
;
144 /* Save the resource list */
145 ResourceCount
= AllocatedResources
->List
[0].PartialResourceList
.Count
;
147 ResourceListSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
148 PartialDescriptors
[ResourceCount
]);
150 DeviceExtension
->AllocatedResources
= ExAllocatePool(PagedPool
, ResourceListSize
);
151 if (DeviceExtension
->AllocatedResources
== NULL
)
153 return STATUS_INSUFFICIENT_RESOURCES
;
156 RtlCopyMemory(DeviceExtension
->AllocatedResources
,
160 /* Get the interrupt level/vector - needed by HwFindAdapter sometimes */
161 for (FullList
= AllocatedResources
->List
;
162 FullList
< AllocatedResources
->List
+ AllocatedResources
->Count
;
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
;
174 if (Descriptor
->Type
== CmResourceTypeInterrupt
)
176 DeviceExtension
->InterruptLevel
= Descriptor
->u
.Interrupt
.Level
;
177 DeviceExtension
->InterruptVector
= Descriptor
->u
.Interrupt
.Vector
;
179 else if (Descriptor
->Type
== CmResourceTypePort
)
181 DeviceExtension
->BaseAddress
= Descriptor
->u
.Port
.Start
;
182 DeviceExtension
->BaseAddrLength
= Descriptor
->u
.Port
.Length
;
183 DeviceExtension
->Flags
= Descriptor
->Flags
;
185 ((struct hc_driver
*)pci_ids
->driver_data
)->flags
&= ~HCD_MEMORY
;
187 else if (Descriptor
->Type
== CmResourceTypeMemory
)
189 DeviceExtension
->BaseAddress
= Descriptor
->u
.Memory
.Start
;
190 DeviceExtension
->BaseAddrLength
= Descriptor
->u
.Memory
.Length
;
191 DeviceExtension
->Flags
= Descriptor
->Flags
;
193 ((struct hc_driver
*)pci_ids
->driver_data
)->flags
|= HCD_MEMORY
;
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
);
206 /* Get bus number from the upper level bus driver. */
207 Size
= sizeof(ULONG
);
208 Status
= IoGetDeviceProperty(
209 DeviceExtension
->PhysicalDeviceObject
,
210 DevicePropertyBusNumber
,
212 &DeviceExtension
->SystemIoBusNumber
,
215 if (!NT_SUCCESS(Status
))
217 DPRINT1("IoGetDeviceProperty DevicePropertyBusNumber failed\n");
218 DeviceExtension
->SystemIoBusNumber
= 0;
221 DPRINT("Busnumber %d\n", DeviceExtension
->SystemIoBusNumber
);
223 /* Init wrapper with this object */
224 return InitLinuxWrapper(DeviceObject
);
228 UsbMpFdoQueryBusRelations(
229 IN PDEVICE_OBJECT DeviceObject
,
230 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
232 PUSBMP_DEVICE_EXTENSION DeviceExtension
;
233 PDEVICE_RELATIONS DeviceRelations
;
234 NTSTATUS Status
= STATUS_SUCCESS
;
236 DeviceExtension
= (PUSBMP_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
238 /* Handling this IRP is easy, as we only
239 * have one child: the root hub
241 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(
243 sizeof(DEVICE_RELATIONS
));
244 if (!DeviceRelations
)
245 return STATUS_INSUFFICIENT_RESOURCES
;
247 /* Fill returned structure */
248 DeviceRelations
->Count
= 1;
249 ObReferenceObject(DeviceExtension
->RootHubPdo
);
250 DeviceRelations
->Objects
[0] = DeviceExtension
->RootHubPdo
;
252 *pDeviceRelations
= DeviceRelations
;
258 IN PDEVICE_OBJECT DeviceObject
,
261 PIO_STACK_LOCATION IrpSp
;
264 ULONG_PTR Information
= 0;
266 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
267 MinorFunction
= IrpSp
->MinorFunction
;
269 switch (MinorFunction
)
271 case IRP_MN_START_DEVICE
: /* 0x00 */
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
);
277 Status
= STATUS_SUCCESS
;
278 if (NT_SUCCESS(Status
) && NT_SUCCESS(Irp
->IoStatus
.Status
))
279 Status
= UsbMpFdoStartDevice(DeviceObject
, Irp
);
283 case IRP_MN_QUERY_REMOVE_DEVICE
: /* 0x01 */
284 case IRP_MN_CANCEL_REMOVE_DEVICE
: /* 0x03 */
286 return ForwardIrpAndForget(DeviceObject
, Irp
);
289 case IRP_MN_REMOVE_DEVICE
: /* 0x02 */
290 case IRP_MN_STOP_DEVICE
: /* 0x04 */
291 case IRP_MN_SURPRISE_REMOVAL
: /* 0x17 */
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
);
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
304 case IRP_MN_QUERY_STOP_DEVICE
: /* 0x05 */
305 case IRP_MN_CANCEL_STOP_DEVICE
: /* 0x06 */
307 Status
= STATUS_SUCCESS
;
310 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* (optional) 0x7 */
312 switch (IrpSp
->Parameters
.QueryDeviceRelations
.Type
)
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
;
322 case RemovalRelations
:
324 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
325 return ForwardIrpAndForget(DeviceObject
, Irp
);
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
);
337 DPRINT1("IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction
);
338 return ForwardIrpAndForget(DeviceObject
, Irp
);
341 Irp
->IoStatus
.Information
= Information
;
342 Irp
->IoStatus
.Status
= Status
;
343 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
348 UsbMpFdoDeviceControl(
349 IN PDEVICE_OBJECT DeviceObject
,
352 PIO_STACK_LOCATION Stack
;
354 PUSBMP_DEVICE_EXTENSION DeviceExtension
;
355 ULONG LengthIn
, LengthOut
;
356 ULONG_PTR Information
= 0;
357 PVOID BufferIn
, BufferOut
;
360 DPRINT("UsbDeviceControlFdo() called\n");
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
);
369 switch (IoControlCode
)
371 case IOCTL_GET_HCD_DRIVERKEY_NAME
:
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
;
380 PUSB_HCD_DRIVERKEY_NAME StringDescriptor
;
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
,
389 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
391 StringDescriptor
->ActualLength
= StringSize
+ FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME
, DriverKeyName
);
392 Information
= LengthOut
;
393 Status
= STATUS_SUCCESS
;
398 case IOCTL_USB_GET_ROOT_HUB_NAME
:
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
;
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
;
413 StringDescriptor
->ActualLength
= RootHubInterfaceName
->Length
+ sizeof(WCHAR
) + FIELD_OFFSET(USB_ROOT_HUB_NAME
, RootHubName
);
414 if (StringDescriptor
->ActualLength
<= LengthOut
)
416 /* Copy root hub name */
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
;
426 Information
= sizeof(USB_ROOT_HUB_NAME
);
427 Status
= STATUS_SUCCESS
;
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
);
441 Irp
->IoStatus
.Information
= Information
;
442 Irp
->IoStatus
.Status
= Status
;
443 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);