reactos/drivers/usb/usbhub/hub_fdo.c

217 lines
8.4 KiB
C

/*
* 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"
#define NDEBUG
#include <debug.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;
}