2 * PROJECT: ReactOS Universal Serial Bus Hub Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbhub/fdo.c
7 * Hervé Poussineau (hpoussin@reactos.org)
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
14 #define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
18 PDEVICE_OBJECT DeviceObject
,
23 DPRINT("Entered Urb Completion\n");
26 // Get the original Irp
28 OriginalIrp
= (PIRP
)Context
;
31 // Update it to match what was returned for the IRP that was passed to RootHub
33 OriginalIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
34 OriginalIrp
->IoStatus
.Information
= Irp
->IoStatus
.Information
;
35 DPRINT("Status %x, Information %x\n", Irp
->IoStatus
.Status
, Irp
->IoStatus
.Information
);
38 // Complete the original Irp
40 IoCompleteRequest(OriginalIrp
, IO_NO_INCREMENT
);
43 // Return this status so the IO Manager doesnt mess with the Irp
45 return STATUS_MORE_PROCESSING_REQUIRED
;
50 PDEVICE_OBJECT RootHubDeviceObject
,
51 IN ULONG IoControlCode
,
53 OUT PVOID OutParameter1
,
54 OUT PVOID OutParameter2
)
58 IO_STATUS_BLOCK IoStatus
;
59 PIO_STACK_LOCATION ForwardStack
, CurrentStack
;
63 // Get the current stack location for the Irp
65 CurrentStack
= IoGetCurrentIrpStackLocation(Irp
);
69 // Pull the Urb from that stack, it will be reused in the Irp sent to RootHub
71 Urb
= (PURB
)CurrentStack
->Parameters
.Others
.Argument1
;
75 // Create the Irp to forward to RootHub
77 ForwardIrp
= IoBuildAsynchronousFsdRequest(IRP_MJ_SHUTDOWN
,
85 DPRINT1("Failed to allocate IRP\n");
86 return STATUS_INSUFFICIENT_RESOURCES
;
90 // Get the new Irps next stack
92 ForwardStack
= IoGetNextIrpStackLocation(ForwardIrp
);
95 // Copy the stack for the current irp into the next stack of new irp
97 RtlCopyMemory(ForwardStack
, CurrentStack
, sizeof(IO_STACK_LOCATION
));
99 IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
100 IoStatus
.Information
= 0;
103 // Mark the Irp from upper driver as pending
105 IoMarkIrpPending(Irp
);
108 // Now set the completion routine for the new Irp.
110 IoSetCompletionRoutine(ForwardIrp
,
111 (PIO_COMPLETION_ROUTINE
)UrbCompletion
,
117 Status
= IoCallDriver(RootHubDeviceObject
, ForwardIrp
);
120 // Always return pending as the completion routine will take care of it
122 return STATUS_PENDING
;
126 USBHUB_PdoHandleInternalDeviceControl(
127 IN PDEVICE_OBJECT DeviceObject
,
131 PIO_STACK_LOCATION Stack
;
132 ULONG_PTR Information
= 0;
133 PHUB_DEVICE_EXTENSION HubDeviceExtension
;
134 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
135 PDEVICE_OBJECT RootHubDeviceObject
;
138 //DPRINT1("UsbhubInternalDeviceControlPdo(%x) called\n", DeviceObject);
141 // get current stack location
143 Stack
= IoGetCurrentIrpStackLocation(Irp
);
147 // Set default status
149 Status
= Irp
->IoStatus
.Status
;
151 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
152 ASSERT(ChildDeviceExtension
->Common
.IsFDO
== FALSE
);
153 HubDeviceExtension
= (PHUB_DEVICE_EXTENSION
)ChildDeviceExtension
->ParentDeviceObject
->DeviceExtension
;
154 RootHubDeviceObject
= HubDeviceExtension
->RootHubPhysicalDeviceObject
;
156 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
158 case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO
:
160 PHUB_DEVICE_EXTENSION DeviceExtension
;
162 DPRINT1("IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n");
163 if (Irp
->AssociatedIrp
.SystemBuffer
== NULL
164 || Stack
->Parameters
.DeviceIoControl
.OutputBufferLength
!= sizeof(PVOID
))
166 Status
= STATUS_INVALID_PARAMETER
;
171 DeviceExtension
= (PHUB_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
173 pHubPointer
= (PVOID
*)Irp
->AssociatedIrp
.SystemBuffer
;
176 Information
= sizeof(PVOID
);
177 Status
= STATUS_SUCCESS
;
181 case IOCTL_INTERNAL_USB_SUBMIT_URB
:
183 //DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB\n");
188 Urb
= (PURB
)Stack
->Parameters
.Others
.Argument1
;
192 // Set the real device handle
194 //DPRINT("UsbdDeviceHandle %x, ChildDeviceHandle %x\n", Urb->UrbHeader.UsbdDeviceHandle, ChildDeviceExtension->UsbDeviceHandle);
196 Urb
->UrbHeader
.UsbdDeviceHandle
= ChildDeviceExtension
->UsbDeviceHandle
;
201 switch (Urb
->UrbHeader
.Function
)
206 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
207 DPRINT1("URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n");
209 case URB_FUNCTION_CLASS_DEVICE
:
210 DPRINT1("URB_FUNCTION_CLASS_DEVICE\n");
212 case URB_FUNCTION_GET_STATUS_FROM_DEVICE
:
213 DPRINT1("URB_FUNCTION_GET_STATUS_FROM_DEVICE\n");
215 case URB_FUNCTION_SELECT_CONFIGURATION
:
216 DPRINT1("URB_FUNCTION_SELECT_CONFIGURATION\n");
218 case URB_FUNCTION_SELECT_INTERFACE
:
219 DPRINT1("URB_FUNCTION_SELECT_INTERFACE\n");
221 case URB_FUNCTION_CLASS_OTHER
:
222 DPRINT1("URB_FUNCTION_CLASS_OTHER\n");
224 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
227 DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER\n");
228 DPRINT1("PipeHandle %x\n", Urb->UrbBulkOrInterruptTransfer.PipeHandle);
229 DPRINT1("TransferFlags %x\n", Urb->UrbBulkOrInterruptTransfer.TransferFlags);
230 DPRINT1("Buffer %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
231 DPRINT1("BufferMDL %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
232 DPRINT1("Length %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
233 DPRINT1("UrbLink %x\n", Urb->UrbBulkOrInterruptTransfer.UrbLink);
234 DPRINT1("hca %x\n", Urb->UrbBulkOrInterruptTransfer.hca);
235 if (Urb->UrbBulkOrInterruptTransfer.TransferFlags == USBD_SHORT_TRANSFER_OK)
242 case URB_FUNCTION_CLASS_INTERFACE
:
243 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
246 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb
->UrbHeader
.Function
);
249 Urb
->UrbHeader
.UsbdDeviceHandle
= ChildDeviceExtension
->UsbDeviceHandle
;
250 //DPRINT1("Stack->CompletionRoutine %x\n", Stack->CompletionRoutine);
252 // Send the request to RootHub
254 Status
= FowardUrbToRootHub(RootHubDeviceObject
, IOCTL_INTERNAL_USB_SUBMIT_URB
, Irp
, Urb
, NULL
);
259 // FIXME: Can these be sent to RootHub?
261 case IOCTL_INTERNAL_USB_RESET_PORT
:
262 DPRINT1("IOCTL_INTERNAL_USB_RESET_PORT\n");
264 case IOCTL_INTERNAL_USB_GET_PORT_STATUS
:
266 PORT_STATUS_CHANGE PortStatus
;
268 PUCHAR PortStatusBits
;
270 PortStatusBits
= (PUCHAR
)Stack
->Parameters
.Others
.Argument1
;
272 // USBD_PORT_ENABLED (bit 0) or USBD_PORT_CONNECTED (bit 1)
274 DPRINT1("IOCTL_INTERNAL_USB_GET_PORT_STATUS\n");
275 DPRINT1("Arg1 %x\n", *PortStatusBits
);
277 if (Stack
->Parameters
.Others
.Argument1
)
279 for (PortId
= 1; PortId
<= HubDeviceExtension
->UsbExtHubInfo
.NumberOfPorts
; PortId
++)
281 Status
= GetPortStatusAndChange(RootHubDeviceObject
, PortId
, &PortStatus
);
282 if (NT_SUCCESS(Status
))
284 DPRINT1("Connect %x\n", ((PortStatus
.Status
& USB_PORT_STATUS_CONNECT
) << 1) << ((PortId
- 1) * 2));
285 DPRINT1("Enable %x\n", ((PortStatus
.Status
& USB_PORT_STATUS_ENABLE
) >> 1) << ((PortId
- 1) * 2));
287 (((PortStatus
.Status
& USB_PORT_STATUS_CONNECT
) << 1) << ((PortId
- 1) * 2)) +
288 (((PortStatus
.Status
& USB_PORT_STATUS_ENABLE
) >> 1) << ((PortId
- 1) * 2));
294 DPRINT1("Arg1 %x\n", *PortStatusBits
);
295 Status
= STATUS_SUCCESS
;
298 case IOCTL_INTERNAL_USB_ENABLE_PORT
:
299 DPRINT1("IOCTL_INTERNAL_USB_ENABLE_PORT\n");
301 case IOCTL_INTERNAL_USB_CYCLE_PORT
:
302 DPRINT1("IOCTL_INTERNAL_USB_CYCLE_PORT\n");
304 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
:
305 DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
309 DPRINT1("Unknown IOCTL code 0x%lx\n", Stack
->Parameters
.DeviceIoControl
.IoControlCode
);
310 Information
= Irp
->IoStatus
.Information
;
311 Status
= Irp
->IoStatus
.Status
;
315 if (Status
!= STATUS_PENDING
)
317 Irp
->IoStatus
.Information
= Information
;
318 Irp
->IoStatus
.Status
= Status
;
319 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
325 USBHUB_PdoStartDevice(
326 IN PDEVICE_OBJECT DeviceObject
,
329 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
331 DPRINT1("USBHUB_PdoStartDevice %x\n", DeviceObject
);
332 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
335 // This should be a PDO
337 ASSERT(ChildDeviceExtension
->Common
.IsFDO
== FALSE
);
340 // FIXME: Fow now assume success
344 return STATUS_SUCCESS
;
349 IN PDEVICE_OBJECT DeviceObject
,
351 OUT ULONG_PTR
* Information
)
353 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
355 PUNICODE_STRING SourceString
= NULL
;
356 PWCHAR ReturnString
= NULL
;
357 NTSTATUS Status
= STATUS_SUCCESS
;
359 IdType
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.QueryId
.IdType
;
360 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
364 case BusQueryDeviceID
:
366 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
367 SourceString
= &ChildDeviceExtension
->usDeviceId
;
370 case BusQueryHardwareIDs
:
372 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
373 SourceString
= &ChildDeviceExtension
->usHardwareIds
;
376 case BusQueryCompatibleIDs
:
378 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
379 SourceString
= &ChildDeviceExtension
->usCompatibleIds
;
382 case BusQueryInstanceID
:
384 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
385 SourceString
= &ChildDeviceExtension
->usInstanceId
;
389 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType
);
390 return STATUS_NOT_SUPPORTED
;
395 ReturnString
= ExAllocatePool(PagedPool
, SourceString
->Length
);
396 RtlCopyMemory(ReturnString
, SourceString
->Buffer
, SourceString
->Length
);
397 DPRINT1("%S\n", ReturnString
);
400 *Information
= (ULONG_PTR
)ReturnString
;
406 USBHUB_PdoQueryDeviceText(
407 IN PDEVICE_OBJECT DeviceObject
,
409 OUT ULONG_PTR
* Information
)
411 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension
;
412 DEVICE_TEXT_TYPE DeviceTextType
;
413 PUNICODE_STRING SourceString
= NULL
;
414 PWCHAR ReturnString
= NULL
;
415 NTSTATUS Status
= STATUS_SUCCESS
;
418 DeviceTextType
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.QueryDeviceText
.DeviceTextType
;
419 LocaleId
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.QueryDeviceText
.LocaleId
;
420 ChildDeviceExtension
= (PHUB_CHILDDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
426 switch (DeviceTextType
)
428 case DeviceTextDescription
:
429 case DeviceTextLocationInformation
:
431 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
434 // does the device provide a text description
436 if (ChildDeviceExtension
->usTextDescription
.Buffer
&& ChildDeviceExtension
->usTextDescription
.Length
)
441 SourceString
= &ChildDeviceExtension
->usTextDescription
;
447 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown device text type 0x%lx\n", DeviceTextType
);
448 Status
= STATUS_NOT_SUPPORTED
;
455 ReturnString
= ExAllocatePool(PagedPool
, SourceString
->Length
);
456 RtlCopyMemory(ReturnString
, SourceString
->Buffer
, SourceString
->Length
);
457 DPRINT1("%S\n", ReturnString
);
458 *Information
= (ULONG_PTR
)ReturnString
;
466 IN PDEVICE_OBJECT DeviceObject
,
471 PIO_STACK_LOCATION Stack
;
472 ULONG_PTR Information
= 0;
473 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension
;
475 UsbChildExtension
= (PHUB_CHILDDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
476 Stack
= IoGetCurrentIrpStackLocation(Irp
);
477 MinorFunction
= Stack
->MinorFunction
;
479 switch (MinorFunction
)
481 case IRP_MN_START_DEVICE
:
483 DPRINT1("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
484 Status
= USBHUB_PdoStartDevice(DeviceObject
, Irp
);
487 case IRP_MN_QUERY_CAPABILITIES
:
489 PDEVICE_CAPABILITIES DeviceCapabilities
;
491 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
493 DeviceCapabilities
= (PDEVICE_CAPABILITIES
)Stack
->Parameters
.DeviceCapabilities
.Capabilities
;
494 // FIXME: capabilities can change with connected device
495 DeviceCapabilities
->LockSupported
= FALSE
;
496 DeviceCapabilities
->EjectSupported
= FALSE
;
497 DeviceCapabilities
->Removable
= TRUE
;
498 DeviceCapabilities
->DockDevice
= FALSE
;
499 DeviceCapabilities
->UniqueID
= FALSE
;
500 DeviceCapabilities
->SilentInstall
= FALSE
;
501 DeviceCapabilities
->RawDeviceOK
= FALSE
;
502 DeviceCapabilities
->SurpriseRemovalOK
= FALSE
;
503 DeviceCapabilities
->HardwareDisabled
= FALSE
;
504 //DeviceCapabilities->NoDisplayInUI = FALSE;
505 DeviceCapabilities
->Address
= UsbChildExtension
->PortNumber
;
506 DeviceCapabilities
->UINumber
= 0;
507 DeviceCapabilities
->DeviceState
[0] = PowerDeviceD0
;
508 for (i
= 0; i
< PowerSystemMaximum
; i
++)
509 DeviceCapabilities
->DeviceState
[i
] = PowerDeviceD3
;
510 //DeviceCapabilities->DeviceWake = PowerDeviceUndefined;
511 DeviceCapabilities
->D1Latency
= 0;
512 DeviceCapabilities
->D2Latency
= 0;
513 DeviceCapabilities
->D3Latency
= 0;
514 Status
= STATUS_SUCCESS
;
517 case IRP_MN_QUERY_RESOURCES
:
519 PCM_RESOURCE_LIST ResourceList
;
521 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
522 ResourceList
= ExAllocatePool(PagedPool
, sizeof(CM_RESOURCE_LIST
));
525 DPRINT1("ExAllocatePool() failed\n");
526 Status
= STATUS_INSUFFICIENT_RESOURCES
;
530 ResourceList
->Count
= 0;
531 Information
= (ULONG_PTR
)ResourceList
;
532 Status
= STATUS_SUCCESS
;
536 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
538 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList
;
539 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
540 ResourceList
= ExAllocatePool(PagedPool
, sizeof(IO_RESOURCE_REQUIREMENTS_LIST
));
543 DPRINT1("ExAllocatePool() failed\n");
544 Status
= STATUS_INSUFFICIENT_RESOURCES
;
548 RtlZeroMemory(ResourceList
, sizeof(IO_RESOURCE_REQUIREMENTS_LIST
));
549 ResourceList
->ListSize
= sizeof(IO_RESOURCE_REQUIREMENTS_LIST
);
550 ResourceList
->AlternativeLists
= 1;
551 ResourceList
->List
->Version
= 1;
552 ResourceList
->List
->Revision
= 1;
553 ResourceList
->List
->Count
= 0;
554 Information
= (ULONG_PTR
)ResourceList
;
555 Status
= STATUS_SUCCESS
;
559 case IRP_MN_QUERY_DEVICE_TEXT
:
561 Status
= USBHUB_PdoQueryDeviceText(DeviceObject
, Irp
, &Information
);
564 case IRP_MN_QUERY_ID
:
566 Status
= USBHUB_PdoQueryId(DeviceObject
, Irp
, &Information
);
569 case IRP_MN_QUERY_BUS_INFORMATION
:
571 PPNP_BUS_INFORMATION BusInfo
;
572 BusInfo
= (PPNP_BUS_INFORMATION
)ExAllocatePool(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
573 RtlCopyMemory(&BusInfo
->BusTypeGuid
,
575 sizeof(BusInfo
->BusTypeGuid
));
576 BusInfo
->LegacyBusType
= PNPBus
;
578 BusInfo
->BusNumber
= 0;
579 Information
= (ULONG_PTR
)BusInfo
;
580 Status
= STATUS_SUCCESS
;
583 case IRP_MN_REMOVE_DEVICE
:
588 Status
= STATUS_SUCCESS
;
593 DPRINT1("PDO IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction
);
594 Information
= Irp
->IoStatus
.Information
;
595 Status
= Irp
->IoStatus
.Status
;
599 Irp
->IoStatus
.Information
= Information
;
600 Irp
->IoStatus
.Status
= Status
;
601 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);