mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 02:05:50 +00:00
[USBHUB]
- Check if FDO is root hub fdo - Partly implement fdo hub initialization - Implement IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE, IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO svn path=/trunk/; revision=55927
This commit is contained in:
parent
9e6f877683
commit
82d9d774ca
6 changed files with 357 additions and 67 deletions
|
@ -3,7 +3,7 @@ add_definitions(-DDEBUG_MODE)
|
|||
|
||||
include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
|
||||
|
||||
add_library(usbhub SHARED fdo.c misc.c pdo.c usbhub.c usbhub.rc)
|
||||
add_library(usbhub SHARED fdo.c misc.c pdo.c hub_fdo.c usbhub.c usbhub.rc)
|
||||
|
||||
target_link_libraries(usbhub ${PSEH_LIB})
|
||||
|
||||
|
|
|
@ -27,71 +27,6 @@ DestroyUsbChildDeviceObject(
|
|||
IN PDEVICE_OBJECT UsbHubDeviceObject,
|
||||
IN LONG PortId);
|
||||
|
||||
NTSTATUS
|
||||
SubmitRequestToRootHub(
|
||||
IN PDEVICE_OBJECT RootHubDeviceObject,
|
||||
IN ULONG IoControlCode,
|
||||
OUT PVOID OutParameter1,
|
||||
OUT PVOID OutParameter2)
|
||||
{
|
||||
KEVENT Event;
|
||||
PIRP Irp;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
NTSTATUS Status;
|
||||
PIO_STACK_LOCATION Stack = NULL;
|
||||
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
//
|
||||
// Build Control Request
|
||||
//
|
||||
Irp = IoBuildDeviceIoControlRequest(IoControlCode,
|
||||
RootHubDeviceObject,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
TRUE,
|
||||
&Event,
|
||||
&IoStatus);
|
||||
|
||||
if (Irp == NULL)
|
||||
{
|
||||
DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize the status block before sending the IRP
|
||||
//
|
||||
IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
IoStatus.Information = 0;
|
||||
|
||||
//
|
||||
// Get Next Stack Location and Initialize it
|
||||
//
|
||||
Stack = IoGetNextIrpStackLocation(Irp);
|
||||
Stack->Parameters.Others.Argument1 = OutParameter1;
|
||||
Stack->Parameters.Others.Argument2 = OutParameter2;
|
||||
|
||||
//
|
||||
// Call RootHub
|
||||
//
|
||||
Status = IoCallDriver(RootHubDeviceObject, Irp);
|
||||
|
||||
//
|
||||
// Its ok to block here as this function is called in an nonarbitrary thread
|
||||
//
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
|
||||
Status = IoStatus.Status;
|
||||
}
|
||||
|
||||
//
|
||||
// The IO Manager will free the IRP
|
||||
//
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
GetPortStatusAndChange(
|
||||
|
@ -1507,6 +1442,31 @@ RootHubInitCallbackFunction(
|
|||
}
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
USBHUB_IsRootHubFDO(
|
||||
IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PDEVICE_OBJECT RootHubPhysicalDeviceObject = NULL;
|
||||
PHUB_DEVICE_EXTENSION HubDeviceExtension;
|
||||
|
||||
// get hub device extension
|
||||
HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
||||
|
||||
// Get the Root Hub Pdo
|
||||
Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject,
|
||||
IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO,
|
||||
&RootHubPhysicalDeviceObject,
|
||||
NULL);
|
||||
|
||||
// FIXME handle error
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
|
||||
// physical device object is only obtained for root hubs
|
||||
return (RootHubPhysicalDeviceObject != NULL);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
USBHUB_FdoStartDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
|
@ -1969,7 +1929,15 @@ USBHUB_FdoHandlePnp(
|
|||
{
|
||||
case IRP_MN_START_DEVICE:
|
||||
{
|
||||
Status = USBHUB_FdoStartDevice(DeviceObject, Irp);
|
||||
if (USBHUB_IsRootHubFDO(DeviceObject))
|
||||
{
|
||||
// start root hub fdo
|
||||
Status = USBHUB_FdoStartDevice(DeviceObject, Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = USBHUB_ParentFDOStartDevice(DeviceObject, Irp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
212
reactos/drivers/usb/usbhub/hub_fdo.c
Normal file
212
reactos/drivers/usb/usbhub/hub_fdo.c
Normal file
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Universal Serial Bus Hub Driver
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/usb/usbhub/hub_fdo.c
|
||||
* PURPOSE: Hub FDO
|
||||
* PROGRAMMERS:
|
||||
* Michael Martin (michael.martin@reactos.org)
|
||||
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||
*/
|
||||
#include "usbhub.h"
|
||||
|
||||
NTSTATUS
|
||||
USBHUB_ParentFDOStartDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PHUB_DEVICE_EXTENSION HubDeviceExtension;
|
||||
PURB Urb, ConfigurationUrb;
|
||||
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||
PUSBD_INTERFACE_LIST_ENTRY InterfaceList;
|
||||
ULONG Index;
|
||||
NTSTATUS Status;
|
||||
|
||||
// get hub device extension
|
||||
HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
||||
|
||||
// Send the StartDevice to lower device object
|
||||
Status = ForwardIrpAndWait(HubDeviceExtension->LowerDeviceObject, Irp);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
// failed to start pdo
|
||||
DPRINT1("Failed to start the RootHub PDO\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
// FIXME get capabilities
|
||||
|
||||
Urb = ExAllocatePool(NonPagedPool, sizeof(URB));
|
||||
if (!Urb)
|
||||
{
|
||||
// no memory
|
||||
DPRINT1("No memory\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
|
||||
// lets get device descriptor
|
||||
UsbBuildGetDescriptorRequest(Urb,
|
||||
sizeof(Urb->UrbControlDescriptorRequest),
|
||||
USB_DEVICE_DESCRIPTOR_TYPE,
|
||||
0,
|
||||
0,
|
||||
&HubDeviceExtension->HubDeviceDescriptor,
|
||||
NULL,
|
||||
sizeof(USB_DEVICE_DESCRIPTOR),
|
||||
NULL);
|
||||
|
||||
|
||||
// get hub device descriptor
|
||||
Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject,
|
||||
IOCTL_INTERNAL_USB_SUBMIT_URB,
|
||||
Urb,
|
||||
NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
// failed to get device descriptor of hub
|
||||
DPRINT1("Failed to get hub device descriptor with Status %x!\n", Status);
|
||||
ExFreePool(Urb);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// now get configuration descriptor
|
||||
UsbBuildGetDescriptorRequest(Urb,
|
||||
sizeof(Urb->UrbControlDescriptorRequest),
|
||||
USB_CONFIGURATION_DESCRIPTOR_TYPE,
|
||||
0,
|
||||
0,
|
||||
&HubDeviceExtension->HubConfigDescriptor,
|
||||
NULL,
|
||||
sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR),
|
||||
NULL);
|
||||
|
||||
// request configuration descriptor
|
||||
Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject,
|
||||
IOCTL_INTERNAL_USB_SUBMIT_URB,
|
||||
Urb,
|
||||
NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
// failed to get configuration descriptor
|
||||
DPRINT1("Failed to get hub configuration descriptor with status %x\n", Status);
|
||||
ExFreePool(Urb);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// sanity checks
|
||||
ASSERT(HubDeviceExtension->HubConfigDescriptor.wTotalLength == sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR));
|
||||
ASSERT(HubDeviceExtension->HubConfigDescriptor.bDescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE);
|
||||
ASSERT(HubDeviceExtension->HubConfigDescriptor.bLength == sizeof(USB_CONFIGURATION_DESCRIPTOR));
|
||||
ASSERT(HubDeviceExtension->HubConfigDescriptor.bNumInterfaces == 1);
|
||||
ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
|
||||
ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
|
||||
ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bNumEndpoints == 1);
|
||||
ASSERT(HubDeviceExtension->HubEndPointDescriptor.bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE);
|
||||
ASSERT(HubDeviceExtension->HubEndPointDescriptor.bLength == sizeof(USB_ENDPOINT_DESCRIPTOR));
|
||||
ASSERT(HubDeviceExtension->HubEndPointDescriptor.bmAttributes == USB_ENDPOINT_TYPE_INTERRUPT);
|
||||
ASSERT(HubDeviceExtension->HubEndPointDescriptor.bEndpointAddress == 0x81); // interrupt in
|
||||
|
||||
// Build hub descriptor request
|
||||
UsbBuildVendorRequest(Urb,
|
||||
URB_FUNCTION_CLASS_DEVICE,
|
||||
sizeof(Urb->UrbControlVendorClassRequest),
|
||||
USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
|
||||
0,
|
||||
USB_REQUEST_GET_DESCRIPTOR,
|
||||
USB_DEVICE_CLASS_RESERVED,
|
||||
0,
|
||||
&HubDeviceExtension->HubDescriptor,
|
||||
NULL,
|
||||
sizeof(USB_HUB_DESCRIPTOR),
|
||||
NULL);
|
||||
|
||||
// send request
|
||||
Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject,
|
||||
IOCTL_INTERNAL_USB_SUBMIT_URB,
|
||||
Urb,
|
||||
NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to get Hub Descriptor Status %x!\n", Status);
|
||||
ExFreePool(Urb);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
// sanity checks
|
||||
ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorLength == sizeof(USB_HUB_DESCRIPTOR));
|
||||
ASSERT(HubDeviceExtension->HubDescriptor.bNumberOfPorts);
|
||||
ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorType == 0x29);
|
||||
|
||||
// store number of ports
|
||||
DPRINT1("NumberOfPorts %lu\n", HubDeviceExtension->HubDescriptor.bNumberOfPorts);
|
||||
HubDeviceExtension->UsbExtHubInfo.NumberOfPorts = HubDeviceExtension->HubDescriptor.bNumberOfPorts;
|
||||
|
||||
// allocate interface list
|
||||
InterfaceList = ExAllocatePool(NonPagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (HubDeviceExtension->HubConfigDescriptor.bNumInterfaces + 1));
|
||||
if (!InterfaceList)
|
||||
{
|
||||
// no memory
|
||||
DPRINT1("No memory\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
// zero list
|
||||
RtlZeroMemory(InterfaceList, sizeof(USBD_INTERFACE_LIST_ENTRY) * (HubDeviceExtension->HubConfigDescriptor.bNumInterfaces + 1));
|
||||
|
||||
// grab all interface descriptors
|
||||
for(Index = 0; Index < HubDeviceExtension->HubConfigDescriptor.bNumInterfaces; Index++)
|
||||
{
|
||||
// Get the first Configuration Descriptor
|
||||
InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension->HubConfigDescriptor,
|
||||
&HubDeviceExtension->HubConfigDescriptor,
|
||||
Index, 0, -1, -1, -1);
|
||||
|
||||
// store in list
|
||||
InterfaceList[Index].InterfaceDescriptor = InterfaceDescriptor;
|
||||
}
|
||||
|
||||
// now create configuration request
|
||||
ConfigurationUrb = USBD_CreateConfigurationRequestEx(&HubDeviceExtension->HubConfigDescriptor,
|
||||
(PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList);
|
||||
if (ConfigurationUrb == NULL)
|
||||
{
|
||||
// failed to build urb
|
||||
DPRINT1("Failed to build configuration urb\n");
|
||||
ExFreePool(Urb);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
// send request
|
||||
Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject,
|
||||
IOCTL_INTERNAL_USB_SUBMIT_URB,
|
||||
ConfigurationUrb,
|
||||
NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to get Hub Descriptor Status %x!\n", Status);
|
||||
ExFreePool(Urb);
|
||||
ExFreePool(ConfigurationUrb);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
// store configuration & pipe handle
|
||||
HubDeviceExtension->ConfigurationHandle = ConfigurationUrb->UrbSelectConfiguration.ConfigurationHandle;
|
||||
HubDeviceExtension->PipeHandle = ConfigurationUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle;
|
||||
DPRINT("Hub Configuration Handle %x\n", HubDeviceExtension->ConfigurationHandle);
|
||||
|
||||
// free urb
|
||||
ExFreePool(ConfigurationUrb);
|
||||
ExFreePool(Urb);
|
||||
|
||||
// FIXME build SCE interrupt request
|
||||
|
||||
// FIXME create pdos
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
|
@ -143,3 +143,68 @@ ForwardIrpAndForget(
|
|||
return IoCallDriver(LowerDevice, Irp);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
SubmitRequestToRootHub(
|
||||
IN PDEVICE_OBJECT RootHubDeviceObject,
|
||||
IN ULONG IoControlCode,
|
||||
OUT PVOID OutParameter1,
|
||||
OUT PVOID OutParameter2)
|
||||
{
|
||||
KEVENT Event;
|
||||
PIRP Irp;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
NTSTATUS Status;
|
||||
PIO_STACK_LOCATION Stack = NULL;
|
||||
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
//
|
||||
// Build Control Request
|
||||
//
|
||||
Irp = IoBuildDeviceIoControlRequest(IoControlCode,
|
||||
RootHubDeviceObject,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
TRUE,
|
||||
&Event,
|
||||
&IoStatus);
|
||||
|
||||
if (Irp == NULL)
|
||||
{
|
||||
DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize the status block before sending the IRP
|
||||
//
|
||||
IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
IoStatus.Information = 0;
|
||||
|
||||
//
|
||||
// Get Next Stack Location and Initialize it
|
||||
//
|
||||
Stack = IoGetNextIrpStackLocation(Irp);
|
||||
Stack->Parameters.Others.Argument1 = OutParameter1;
|
||||
Stack->Parameters.Others.Argument2 = OutParameter2;
|
||||
|
||||
//
|
||||
// Call RootHub
|
||||
//
|
||||
Status = IoCallDriver(RootHubDeviceObject, Irp);
|
||||
|
||||
//
|
||||
// Its ok to block here as this function is called in an nonarbitrary thread
|
||||
//
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
|
||||
Status = IoStatus.Status;
|
||||
}
|
||||
|
||||
//
|
||||
// The IO Manager will free the IRP
|
||||
//
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
|
|
@ -339,8 +339,39 @@ USBHUB_PdoHandleInternalDeviceControl(
|
|||
DPRINT1("IOCTL_INTERNAL_USB_CYCLE_PORT\n");
|
||||
break;
|
||||
case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
|
||||
{
|
||||
DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
|
||||
if (Stack->Parameters.Others.Argument1)
|
||||
{
|
||||
// store device handle
|
||||
*(PVOID *)Stack->Parameters.Others.Argument1 = (PVOID)ChildDeviceExtension->UsbDeviceHandle;
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// invalid parameter
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
|
||||
{
|
||||
if (Stack->Parameters.Others.Argument1)
|
||||
{
|
||||
// inform caller that it is a real usb hub
|
||||
*(PVOID *)Stack->Parameters.Others.Argument1 = NULL;
|
||||
}
|
||||
|
||||
if (Stack->Parameters.Others.Argument2)
|
||||
{
|
||||
// output device object
|
||||
*(PVOID *)Stack->Parameters.Others.Argument2 = DeviceObject;
|
||||
}
|
||||
|
||||
// done
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
DPRINT1("Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode);
|
||||
|
|
|
@ -142,6 +142,13 @@ ForwardIrpAndForget(
|
|||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
SubmitRequestToRootHub(
|
||||
IN PDEVICE_OBJECT RootHubDeviceObject,
|
||||
IN ULONG IoControlCode,
|
||||
OUT PVOID OutParameter1,
|
||||
OUT PVOID OutParameter2);
|
||||
|
||||
// pdo.c
|
||||
NTSTATUS
|
||||
USBHUB_PdoHandlePnp(
|
||||
|
@ -170,3 +177,10 @@ GetPortStatusAndChange(
|
|||
IN PDEVICE_OBJECT RootHubDeviceObject,
|
||||
IN ULONG PortId,
|
||||
OUT PPORT_STATUS_CHANGE StatusChange);
|
||||
|
||||
// hub_fdo.c
|
||||
|
||||
NTSTATUS
|
||||
USBHUB_ParentFDOStartDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
Loading…
Add table
Add a link
Reference in a new issue