mirror of
https://github.com/reactos/reactos.git
synced 2024-10-18 23:18:56 +00:00
3063e3bf5e
- Implement constructing CompatibleIds string using device descriptor. However, if the Class of the device descriptor is 0, then Class, SubClass and Prot which make up this string must come from the Interface. - Change Ids and Descriptions to Unicode Strings. - Move the creating of Id strings to one place, CreateDeviceIds, and called it at device creation. svn path=/branches/usb-bringup/; revision=51641
336 lines
10 KiB
C
336 lines
10 KiB
C
/*
|
|
* PROJECT: ReactOS Universal Serial Bus Hub Driver
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: drivers/usb/usbhub/fdo.c
|
|
* PURPOSE: Handle PDO
|
|
* PROGRAMMERS:
|
|
* Hervé Poussineau (hpoussin@reactos.org)
|
|
* Michael Martin (michael.martin@reactos.org)
|
|
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
|
*/
|
|
|
|
#define NDEBUG
|
|
#include "usbhub.h"
|
|
|
|
#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
|
|
|
|
NTSTATUS
|
|
USBHUB_PdoHandleInternalDeviceControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION Stack;
|
|
ULONG_PTR Information = 0;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT1("UsbhubInternalDeviceControlPdo(%x) called\n", DeviceObject);
|
|
|
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
|
Status = Irp->IoStatus.Status;
|
|
|
|
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
|
|
{
|
|
case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO:
|
|
{
|
|
PHUB_DEVICE_EXTENSION DeviceExtension;
|
|
|
|
DPRINT1("IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n");
|
|
if (Irp->AssociatedIrp.SystemBuffer == NULL
|
|
|| Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(PVOID))
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
PVOID* pHubPointer;
|
|
DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
pHubPointer = (PVOID*)Irp->AssociatedIrp.SystemBuffer;
|
|
// FIXME
|
|
*pHubPointer = NULL;
|
|
Information = sizeof(PVOID);
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
DPRINT1("Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode);
|
|
Information = Irp->IoStatus.Information;
|
|
Status = Irp->IoStatus.Status;
|
|
}
|
|
}
|
|
|
|
Irp->IoStatus.Information = Information;
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
USBHUB_PdoStartDevice(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
|
|
//NTSTATUS Status;
|
|
DPRINT1("USBHUB_PdoStartDevice %x\n", DeviceObject);
|
|
ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// This should be a PDO
|
|
//
|
|
ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE);
|
|
|
|
//
|
|
// FIXME: Fow now assume success
|
|
//
|
|
|
|
UNIMPLEMENTED
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
USBHUB_PdoQueryId(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
OUT ULONG_PTR* Information)
|
|
{
|
|
PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
|
|
ULONG IdType;
|
|
PUNICODE_STRING SourceString = NULL;
|
|
PWCHAR ReturnString = NULL;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
|
|
ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
switch (IdType)
|
|
{
|
|
case BusQueryDeviceID:
|
|
{
|
|
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
|
|
SourceString = &ChildDeviceExtension->usDeviceId;
|
|
break;
|
|
}
|
|
case BusQueryHardwareIDs:
|
|
{
|
|
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
|
|
SourceString = &ChildDeviceExtension->usHardwareIds;
|
|
break;
|
|
}
|
|
case BusQueryCompatibleIDs:
|
|
{
|
|
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
|
|
SourceString = &ChildDeviceExtension->usCompatibleIds;
|
|
break;
|
|
}
|
|
case BusQueryInstanceID:
|
|
{
|
|
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
|
|
SourceString = &ChildDeviceExtension->usInstanceId;
|
|
break;
|
|
}
|
|
default:
|
|
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
if (SourceString)
|
|
{
|
|
ReturnString = ExAllocatePool(PagedPool, SourceString->Length);
|
|
RtlCopyMemory(ReturnString, SourceString->Buffer, SourceString->Length);
|
|
DPRINT1("%S\n", ReturnString);
|
|
}
|
|
|
|
*Information = (ULONG_PTR)ReturnString;
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
USBHUB_PdoQueryDeviceText(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
OUT ULONG_PTR* Information)
|
|
{
|
|
PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
|
|
DEVICE_TEXT_TYPE DeviceTextType;
|
|
PUNICODE_STRING SourceString = NULL;
|
|
PWCHAR ReturnString = NULL;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
LCID LocaleId;
|
|
|
|
DeviceTextType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.DeviceTextType;
|
|
LocaleId = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.LocaleId;
|
|
ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// FIXME: LocaleId
|
|
//
|
|
|
|
switch (DeviceTextType)
|
|
{
|
|
case DeviceTextDescription:
|
|
case DeviceTextLocationInformation:
|
|
{
|
|
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
|
|
SourceString = &ChildDeviceExtension->usTextDescription;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown device text type 0x%lx\n", DeviceTextType);
|
|
Status = STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (SourceString)
|
|
{
|
|
ReturnString = ExAllocatePool(PagedPool, SourceString->Length);
|
|
RtlCopyMemory(ReturnString, SourceString->Buffer, SourceString->Length);
|
|
DPRINT1("%S\n", ReturnString);
|
|
*Information = (ULONG_PTR)ReturnString;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
USBHUB_PdoHandlePnp(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
ULONG MinorFunction;
|
|
PIO_STACK_LOCATION Stack;
|
|
ULONG_PTR Information = 0;
|
|
NTSTATUS Status;
|
|
|
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
|
MinorFunction = Stack->MinorFunction;
|
|
|
|
switch (MinorFunction)
|
|
{
|
|
case IRP_MN_START_DEVICE:
|
|
{
|
|
DPRINT1("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
|
|
Status = USBHUB_PdoStartDevice(DeviceObject, Irp);
|
|
break;
|
|
}
|
|
case IRP_MN_QUERY_CAPABILITIES:
|
|
{
|
|
PDEVICE_CAPABILITIES DeviceCapabilities;
|
|
ULONG i;
|
|
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
|
|
|
|
DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities;
|
|
// FIXME: capabilities can change with connected device
|
|
DeviceCapabilities->LockSupported = TRUE;
|
|
DeviceCapabilities->EjectSupported = TRUE;
|
|
DeviceCapabilities->Removable = TRUE;
|
|
DeviceCapabilities->DockDevice = FALSE;
|
|
DeviceCapabilities->UniqueID = TRUE;
|
|
DeviceCapabilities->SilentInstall = TRUE;
|
|
DeviceCapabilities->RawDeviceOK = FALSE;
|
|
DeviceCapabilities->SurpriseRemovalOK = TRUE;
|
|
DeviceCapabilities->HardwareDisabled = FALSE;
|
|
//DeviceCapabilities->NoDisplayInUI = FALSE;
|
|
DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
|
|
for (i = 0; i < PowerSystemMaximum; i++)
|
|
DeviceCapabilities->DeviceState[i] = PowerDeviceD3;
|
|
//DeviceCapabilities->DeviceWake = PowerDeviceUndefined;
|
|
DeviceCapabilities->D1Latency = 0;
|
|
DeviceCapabilities->D2Latency = 0;
|
|
DeviceCapabilities->D3Latency = 0;
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
case IRP_MN_QUERY_RESOURCES:
|
|
{
|
|
PCM_RESOURCE_LIST ResourceList;
|
|
|
|
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
|
|
ResourceList = ExAllocatePool(PagedPool, sizeof(CM_RESOURCE_LIST));
|
|
if (!ResourceList)
|
|
{
|
|
DPRINT1("ExAllocatePool() failed\n");
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
ResourceList->Count = 0;
|
|
Information = (ULONG_PTR)ResourceList;
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
}
|
|
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
|
|
{
|
|
PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
|
|
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
|
|
ResourceList = ExAllocatePool(PagedPool, sizeof(IO_RESOURCE_REQUIREMENTS_LIST));
|
|
if (!ResourceList)
|
|
{
|
|
DPRINT1("ExAllocatePool() failed\n");
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
RtlZeroMemory(ResourceList, sizeof(IO_RESOURCE_REQUIREMENTS_LIST));
|
|
ResourceList->ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
|
|
ResourceList->AlternativeLists = 1;
|
|
ResourceList->List->Version = 1;
|
|
ResourceList->List->Revision = 1;
|
|
ResourceList->List->Count = 0;
|
|
Information = (ULONG_PTR)ResourceList;
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
}
|
|
case IRP_MN_QUERY_DEVICE_TEXT:
|
|
{
|
|
Status = USBHUB_PdoQueryDeviceText(DeviceObject, Irp, &Information);
|
|
break;
|
|
}
|
|
case IRP_MN_QUERY_ID:
|
|
{
|
|
Status = USBHUB_PdoQueryId(DeviceObject, Irp, &Information);
|
|
break;
|
|
}
|
|
case IRP_MN_QUERY_BUS_INFORMATION:
|
|
{
|
|
PPNP_BUS_INFORMATION BusInfo;
|
|
BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
|
|
RtlCopyMemory(&BusInfo->BusTypeGuid,
|
|
&GUID_BUS_TYPE_USB,
|
|
sizeof(BusInfo->BusTypeGuid));
|
|
BusInfo->LegacyBusType = PNPBus;
|
|
// FIXME
|
|
BusInfo->BusNumber = 0;
|
|
Information = (ULONG_PTR)BusInfo;
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
case IRP_MN_REMOVE_DEVICE:
|
|
{
|
|
//
|
|
// FIXME
|
|
//
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
default:
|
|
{
|
|
DPRINT1("PDO IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
|
|
Information = Irp->IoStatus.Information;
|
|
Status = Irp->IoStatus.Status;
|
|
}
|
|
}
|
|
|
|
Irp->IoStatus.Information = Information;
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return Status;
|
|
}
|
|
|