1033 lines
24 KiB
C
1033 lines
24 KiB
C
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
busif.c
|
|
|
|
Abstract:
|
|
|
|
Exports PnP services thru a bus interface, this eleminates
|
|
any dependency of usbhub on usbd.sys with regard to the 'port'
|
|
driver support.
|
|
|
|
Old services have been renamed ServiceNameX and a dummy entrypoint
|
|
added
|
|
|
|
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Notes:
|
|
|
|
|
|
|
|
Revision History:
|
|
|
|
10-29-95 : created
|
|
|
|
--*/
|
|
|
|
#include "wdm.h"
|
|
#include "stdarg.h"
|
|
#include "stdio.h"
|
|
|
|
|
|
//#include "usbdi.h" //public data structures
|
|
#include "usbdi.h"
|
|
#include "hcdi.h"
|
|
|
|
#include "usb200.h"
|
|
#include "usbd.h" //private data strutures
|
|
#include <initguid.h>
|
|
#include "hubbusif.h" // hub service bus interface
|
|
#include "usbbusif.h" // hub service bus interface
|
|
|
|
|
|
#ifdef USBD_DRIVER // USBPORT supercedes most of USBD, so we will remove
|
|
// the obsolete code by compiling it only if
|
|
// USBD_DRIVER is set.
|
|
|
|
|
|
NTSTATUS
|
|
USBD_RestoreDeviceX(
|
|
IN OUT PUSBD_DEVICE_DATA OldDeviceData,
|
|
IN OUT PUSBD_DEVICE_DATA NewDeviceData,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
NTSTATUS
|
|
USBD_CreateDeviceX(
|
|
IN OUT PUSBD_DEVICE_DATA *DeviceData,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN BOOLEAN DeviceIsLowSpeed,
|
|
IN ULONG MaxPacketSize_Endpoint0,
|
|
IN OUT PULONG DeviceHackFlags
|
|
);
|
|
|
|
NTSTATUS
|
|
USBD_RemoveDeviceX(
|
|
IN PUSBD_DEVICE_DATA DeviceData,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN UCHAR Flags
|
|
);
|
|
|
|
NTSTATUS
|
|
USBD_InitializeDeviceX(
|
|
IN PUSBD_DEVICE_DATA DeviceData,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PUSB_DEVICE_DESCRIPTOR DeviceDescriptor,
|
|
IN ULONG DeviceDescriptorLength,
|
|
IN OUT PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor,
|
|
IN ULONG ConfigDescriptorLength
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
USBD_BusCreateDevice(
|
|
IN PVOID BusContext,
|
|
IN OUT PUSB_DEVICE_HANDLE *DeviceHandle,
|
|
IN PUSB_DEVICE_HANDLE HubDevicehandle,
|
|
IN USHORT PortStatus,
|
|
IN USHORT PortNumber
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
BOOLEAN isLowSpeed;
|
|
PDEVICE_OBJECT rootHubPdo;
|
|
ULONG hackFlags;
|
|
PUSBD_DEVICE_DATA deviceData;
|
|
|
|
rootHubPdo = BusContext;
|
|
|
|
isLowSpeed = (PortStatus & USB_PORT_STATUS_LOW_SPEED) ? TRUE : FALSE;
|
|
|
|
ntStatus = USBD_CreateDeviceX(
|
|
&deviceData,
|
|
rootHubPdo,
|
|
isLowSpeed,
|
|
0, // max packet size override, it turns out we
|
|
// never use this
|
|
&hackFlags);
|
|
|
|
*DeviceHandle = deviceData;
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBD_BusInitializeDevice(
|
|
IN PVOID BusContext,
|
|
IN OUT PUSB_DEVICE_HANDLE DeviceHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
PDEVICE_OBJECT rootHubPdo;
|
|
|
|
rootHubPdo = BusContext;
|
|
|
|
ntStatus = USBD_InitializeDeviceX(DeviceHandle,
|
|
rootHubPdo,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBD_BusRemoveDevice(
|
|
IN PVOID BusContext,
|
|
IN OUT PUSB_DEVICE_HANDLE DeviceHandle,
|
|
IN ULONG Flags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
PDEVICE_OBJECT rootHubPdo;
|
|
|
|
rootHubPdo = BusContext;
|
|
|
|
// note old remove device only supports 8 flags
|
|
|
|
ntStatus = USBD_RemoveDeviceX(
|
|
DeviceHandle,
|
|
rootHubPdo,
|
|
(UCHAR) Flags);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBD_BusGetUsbDescriptors(
|
|
IN PVOID BusContext,
|
|
IN OUT PUSB_DEVICE_HANDLE DeviceHandle,
|
|
IN OUT PUCHAR DeviceDescriptorBuffer,
|
|
IN OUT PULONG DeviceDescriptorBufferLength,
|
|
IN OUT PUCHAR ConfigDescriptorBuffer,
|
|
IN OUT PULONG ConfigDescriptorBufferLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
PDEVICE_OBJECT rootHubPdo;
|
|
PUSBD_DEVICE_DATA deviceData = DeviceHandle;
|
|
|
|
rootHubPdo = BusContext;
|
|
|
|
// use the cached device descriptor
|
|
if (DeviceDescriptorBuffer && *DeviceDescriptorBufferLength) {
|
|
RtlCopyMemory(DeviceDescriptorBuffer,
|
|
&deviceData->DeviceDescriptor,
|
|
*DeviceDescriptorBufferLength);
|
|
*DeviceDescriptorBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
|
|
}
|
|
|
|
// Fetch the config descriptor. If all that is desired is the 9 byte
|
|
// config descriptor header, just return the cached config descriptor
|
|
// header so that we don't send back to back requests for just the 9 byte
|
|
// header to the device. That seems to confuse some devices, some usb
|
|
// audio devices in particular when enumerating on OHCI host controllers.
|
|
//
|
|
if (ConfigDescriptorBuffer &&
|
|
*ConfigDescriptorBufferLength == sizeof(USB_CONFIGURATION_DESCRIPTOR))
|
|
{
|
|
RtlCopyMemory(ConfigDescriptorBuffer,
|
|
&deviceData->ConfigDescriptor,
|
|
sizeof(USB_CONFIGURATION_DESCRIPTOR));
|
|
}
|
|
else if (ConfigDescriptorBuffer && *ConfigDescriptorBufferLength) {
|
|
|
|
ULONG bytesReturned;
|
|
|
|
ntStatus =
|
|
USBD_SendCommand(deviceData,
|
|
rootHubPdo,
|
|
STANDARD_COMMAND_GET_DESCRIPTOR,
|
|
USB_DESCRIPTOR_MAKE_TYPE_AND_INDEX(
|
|
USB_CONFIGURATION_DESCRIPTOR_TYPE, 0),
|
|
0,
|
|
(USHORT) *ConfigDescriptorBufferLength,
|
|
(PUCHAR) ConfigDescriptorBuffer,
|
|
*ConfigDescriptorBufferLength,
|
|
&bytesReturned,
|
|
NULL);
|
|
|
|
if (NT_SUCCESS(ntStatus) &&
|
|
bytesReturned < sizeof(USB_CONFIGURATION_DESCRIPTOR)) {
|
|
// truncated config descriptor returned
|
|
USBD_KdPrint(0,
|
|
("'WARNING: Truncated Config Descriptor returned - get JD\n"));
|
|
|
|
ntStatus = STATUS_DEVICE_DATA_ERROR;
|
|
}
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBD_BusRestoreDevice(
|
|
IN PVOID BusContext,
|
|
IN OUT PUSB_DEVICE_HANDLE OldDeviceHandle,
|
|
IN OUT PUSB_DEVICE_HANDLE NewDeviceHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
PDEVICE_OBJECT rootHubPdo;
|
|
|
|
rootHubPdo = BusContext;
|
|
|
|
ntStatus = USBD_RestoreDeviceX(OldDeviceHandle,
|
|
NewDeviceHandle,
|
|
rootHubPdo);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBD_BusGetUsbDeviceHackFlags(
|
|
IN PVOID BusContext,
|
|
IN PUSB_DEVICE_HANDLE DeviceHandle,
|
|
IN OUT PULONG HackFlags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
PDEVICE_OBJECT rootHubPdo;
|
|
PUSBD_DEVICE_DATA deviceData = DeviceHandle;
|
|
|
|
rootHubPdo = BusContext;
|
|
|
|
TEST_TRAP();
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBD_BusGetUsbPortHackFlags(
|
|
IN PVOID BusContext,
|
|
IN OUT PULONG HackFlags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
PDEVICE_OBJECT rootHubPdo;
|
|
PUSBD_EXTENSION deviceExtensionUsbd;
|
|
|
|
rootHubPdo = BusContext;
|
|
*HackFlags = 0;
|
|
|
|
deviceExtensionUsbd = ((PUSBD_EXTENSION)rootHubPdo->DeviceExtension)->TrueDeviceExtension;
|
|
if (deviceExtensionUsbd->DiagnosticMode) {
|
|
*HackFlags |= USBD_DEVHACK_SET_DIAG_ID;
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
VOID
|
|
USBD_BusInterfaceReference(
|
|
IN PVOID BusContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
}
|
|
|
|
|
|
VOID
|
|
USBD_BusInterfaceDereference(
|
|
IN PVOID BusContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBD_BusQueryBusTime(
|
|
IN PVOID BusContext,
|
|
IN PULONG CurrentFrame
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
returns the current USB frame
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
PUSBD_EXTENSION deviceExtensionUsbd;
|
|
PDEVICE_OBJECT rootHubPdo = BusContext;
|
|
|
|
deviceExtensionUsbd = rootHubPdo->DeviceExtension;
|
|
deviceExtensionUsbd = deviceExtensionUsbd->TrueDeviceExtension;
|
|
|
|
return deviceExtensionUsbd->HcdGetCurrentFrame(
|
|
deviceExtensionUsbd->HcdDeviceObject,
|
|
CurrentFrame);
|
|
}
|
|
|
|
VOID
|
|
USBD_GetUSBDIVersion(
|
|
PUSBD_VERSION_INFORMATION VersionInformation
|
|
);
|
|
|
|
VOID
|
|
USBD_BusGetUSBDIVersion(
|
|
IN PVOID BusContext,
|
|
IN OUT PUSBD_VERSION_INFORMATION VersionInformation,
|
|
IN OUT PULONG HcdCapabilities
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
returns the current USB frame
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
PUSBD_EXTENSION deviceExtensionUsbd;
|
|
PDEVICE_OBJECT rootHubPdo = BusContext;
|
|
|
|
deviceExtensionUsbd = rootHubPdo->DeviceExtension;
|
|
deviceExtensionUsbd = deviceExtensionUsbd->TrueDeviceExtension;
|
|
|
|
USBD_GetUSBDIVersion(VersionInformation);
|
|
|
|
*HcdCapabilities = 0;
|
|
|
|
if (deviceExtensionUsbd->HcdSubmitIsoUrb != NULL) {
|
|
*HcdCapabilities = USB_HCD_CAPS_SUPPORTS_RT_THREADS;
|
|
}
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBD_BusSubmitIsoOutUrb(
|
|
IN PVOID BusContext,
|
|
IN OUT PURB Urb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
PUSBD_EXTENSION deviceExtensionUsbd;
|
|
PDEVICE_OBJECT rootHubPdo = BusContext;
|
|
NTSTATUS ntStatus;
|
|
// PUSBD_DEVICE_DATA deviceData;
|
|
PUSBD_PIPE pipeHandle;
|
|
|
|
pipeHandle = (PUSBD_PIPE)Urb->UrbIsochronousTransfer.PipeHandle;
|
|
|
|
ASSERT_PIPE(pipeHandle);
|
|
deviceExtensionUsbd = rootHubPdo->DeviceExtension;
|
|
deviceExtensionUsbd = deviceExtensionUsbd->TrueDeviceExtension;
|
|
|
|
((PHCD_URB)Urb)->HcdUrbCommonTransfer.hca.HcdEndpoint =
|
|
pipeHandle->HcdEndpoint;
|
|
|
|
if (pipeHandle->EndpointDescriptor.bEndpointAddress &
|
|
USB_ENDPOINT_DIRECTION_MASK) {
|
|
USBD_SET_TRANSFER_DIRECTION_IN(((PHCD_URB)Urb)->HcdUrbCommonTransfer.TransferFlags);
|
|
} else {
|
|
USBD_SET_TRANSFER_DIRECTION_OUT(((PHCD_URB)Urb)->HcdUrbCommonTransfer.TransferFlags);
|
|
}
|
|
|
|
if (deviceExtensionUsbd->HcdSubmitIsoUrb == NULL) {
|
|
// fast iso interface not supported by HCD
|
|
TEST_TRAP();
|
|
ntStatus = STATUS_NOT_SUPPORTED;
|
|
} else {
|
|
ntStatus = deviceExtensionUsbd->HcdSubmitIsoUrb(
|
|
deviceExtensionUsbd->HcdDeviceObject,
|
|
Urb);
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBD_BusQueryDeviceInformation(
|
|
IN PVOID BusContext,
|
|
IN PUSB_DEVICE_HANDLE DeviceHandle,
|
|
IN OUT PVOID DeviceInformationBuffer,
|
|
IN ULONG DeviceInformationBufferLength,
|
|
IN OUT PULONG LengthOfDataCopied
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
ULONG need;
|
|
PUSBD_CONFIG configHandle;
|
|
ULONG i,j,k;
|
|
PUSB_DEVICE_INFORMATION_0 level_0 = DeviceInformationBuffer;
|
|
PUSB_LEVEL_INFORMATION levelInfo = DeviceInformationBuffer;
|
|
ULONG numberOfPipes = 0;
|
|
PUSBD_DEVICE_DATA deviceData = DeviceHandle;
|
|
|
|
|
|
// bugbug
|
|
// need more validation here
|
|
|
|
PAGED_CODE();
|
|
|
|
*LengthOfDataCopied = 0;
|
|
|
|
if (DeviceInformationBufferLength < sizeof(*levelInfo)) {
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
if (levelInfo->InformationLevel > 0) {
|
|
// usbd only supports level 0
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
// figure out how much room we need
|
|
configHandle = deviceData->ConfigurationHandle;
|
|
if (configHandle) {
|
|
|
|
// count the pipes in each interface
|
|
for (i=0;
|
|
i< configHandle->ConfigurationDescriptor->bNumInterfaces;
|
|
i++) {
|
|
numberOfPipes +=
|
|
configHandle->InterfaceHandle[i]->
|
|
InterfaceInformation->NumberOfPipes;
|
|
}
|
|
|
|
}
|
|
|
|
need = (numberOfPipes-1) * sizeof(USB_PIPE_INFORMATION_0) +
|
|
sizeof(USB_DEVICE_INFORMATION_0);
|
|
|
|
|
|
if (DeviceInformationBufferLength < need) {
|
|
// report how much space if possible
|
|
levelInfo->ActualLength = need;
|
|
*LengthOfDataCopied = sizeof(*levelInfo);
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
RtlZeroMemory(level_0, need);
|
|
|
|
//
|
|
// enough room, fill in the buffer
|
|
//
|
|
|
|
level_0->InformationLevel = 0;
|
|
level_0->ActualLength = need;
|
|
level_0->DeviceAddress = deviceData->DeviceAddress;
|
|
level_0->DeviceDescriptor = deviceData->DeviceDescriptor;
|
|
|
|
if (deviceData->LowSpeed) {
|
|
level_0->DeviceSpeed = UsbLowSpeed;
|
|
} else {
|
|
level_0->DeviceSpeed = UsbFullSpeed;
|
|
}
|
|
|
|
// if (DeviceData->xxx) {
|
|
level_0->DeviceType = Usb11Device;
|
|
// } else {
|
|
// level_0->DeviceSpeed = UsbFullSpeed;
|
|
// }
|
|
|
|
// level_0->PortNumber = xxx;
|
|
level_0->NumberOfOpenPipes = numberOfPipes;
|
|
level_0->CurrentConfigurationValue = 0;
|
|
// get the pipe information
|
|
if (configHandle) {
|
|
|
|
level_0->CurrentConfigurationValue =
|
|
configHandle->ConfigurationDescriptor->bConfigurationValue;
|
|
|
|
j=0;
|
|
for (i=0;
|
|
i<configHandle->ConfigurationDescriptor->bNumInterfaces;
|
|
i++) {
|
|
|
|
PUSBD_INTERFACE interfaceHandle =
|
|
configHandle->InterfaceHandle[i];
|
|
|
|
for (k=0;
|
|
k<interfaceHandle->InterfaceInformation->NumberOfPipes;
|
|
k++, j++) {
|
|
|
|
ASSERT(j < numberOfPipes);
|
|
|
|
level_0->PipeList[j].ScheduleOffset =
|
|
interfaceHandle->PipeHandle[k].ScheduleOffset;
|
|
RtlCopyMemory(&level_0->PipeList[j].
|
|
EndpointDescriptor,
|
|
&interfaceHandle->PipeHandle[k].
|
|
EndpointDescriptor,
|
|
sizeof(USB_ENDPOINT_DESCRIPTOR));
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
*LengthOfDataCopied = need;
|
|
|
|
// dump the level data returned
|
|
USBD_KdPrint(1, (" USBD level 0 Device Information:\n"));
|
|
USBD_KdPrint(1, (" InformationLevel %d\n",
|
|
level_0->InformationLevel));
|
|
// USBD_KdPrint(1, (" DeviceDescriptor %d\n",
|
|
// level_0->InformationLevel));
|
|
USBD_KdPrint(1, (" ActualLength %d\n",
|
|
level_0->ActualLength));
|
|
USBD_KdPrint(1, (" DeviceSpeed %d\n",
|
|
level_0->DeviceSpeed));
|
|
USBD_KdPrint(1, (" PortNumber %d\n",
|
|
level_0->PortNumber));
|
|
USBD_KdPrint(1, (" CurrentConfigurationValue %d\n",
|
|
level_0->CurrentConfigurationValue));
|
|
USBD_KdPrint(1, (" DeviceAddress %d\n",
|
|
level_0->DeviceAddress));
|
|
USBD_KdPrint(1, (" NumberOfOpenPipes %d\n",
|
|
level_0->NumberOfOpenPipes));
|
|
|
|
for (i=0; i< level_0->NumberOfOpenPipes; i++) {
|
|
USBD_KdPrint(1, (" ScheduleOffset[%d] %d\n", i,
|
|
level_0->PipeList[i].ScheduleOffset));
|
|
USBD_KdPrint(1, (" MaxPacket %d\n",
|
|
level_0->PipeList[i].EndpointDescriptor.wMaxPacketSize));
|
|
USBD_KdPrint(1, (" Interval %d\n",
|
|
level_0->PipeList[i].EndpointDescriptor.bInterval));
|
|
// USBD_KdPrint(1, ("' \n", level_0->));
|
|
// USBD_KdPrint(1, ("' \n", level_0->));
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBD_BusQueryBusInformation(
|
|
IN PVOID BusContext,
|
|
IN ULONG Level,
|
|
IN OUT PVOID BusInformationBuffer,
|
|
IN OUT PULONG BusInformationBufferLength,
|
|
OUT PULONG BusInformationActulaLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus = STATUS_NOT_SUPPORTED;
|
|
PUSB_BUS_INFORMATION_LEVEL_0 level_0;
|
|
PUSB_BUS_INFORMATION_LEVEL_1 level_1;
|
|
PDEVICE_OBJECT rootHubPdo = BusContext;
|
|
PUSBD_EXTENSION deviceExtensionUsbd;
|
|
ULONG len, need;
|
|
|
|
deviceExtensionUsbd = rootHubPdo->DeviceExtension;
|
|
deviceExtensionUsbd = deviceExtensionUsbd->TrueDeviceExtension;
|
|
|
|
switch (Level) {
|
|
case 0:
|
|
level_0 = BusInformationBuffer;
|
|
if (BusInformationActulaLength != NULL) {
|
|
*BusInformationActulaLength = sizeof(*level_0);
|
|
}
|
|
|
|
if (*BusInformationBufferLength >= sizeof(*level_0)) {
|
|
*BusInformationBufferLength = sizeof(*level_0);
|
|
|
|
level_0->TotalBandwidth = 12000; // 12 Mbits
|
|
level_0->ConsumedBandwidth =
|
|
deviceExtensionUsbd->HcdGetConsumedBW(
|
|
deviceExtensionUsbd->HcdDeviceObject);
|
|
|
|
ntStatus = STATUS_SUCCESS;
|
|
} else {
|
|
ntStatus = STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
level_1 = BusInformationBuffer;
|
|
|
|
need = sizeof(*level_1) +
|
|
deviceExtensionUsbd->DeviceLinkUnicodeString.Length;
|
|
|
|
if (BusInformationActulaLength != NULL) {
|
|
*BusInformationActulaLength = need;
|
|
}
|
|
|
|
if (*BusInformationBufferLength >= need) {
|
|
*BusInformationBufferLength = need;
|
|
|
|
level_1->TotalBandwidth = 12000; // 12 Mbits
|
|
level_1->ConsumedBandwidth =
|
|
deviceExtensionUsbd->HcdGetConsumedBW(
|
|
deviceExtensionUsbd->HcdDeviceObject);
|
|
|
|
level_1->ControllerNameLength =
|
|
deviceExtensionUsbd->DeviceLinkUnicodeString.Length;
|
|
|
|
len = deviceExtensionUsbd->DeviceLinkUnicodeString.Length;
|
|
|
|
if (len > sizeof(level_1->ControllerNameUnicodeString)) {
|
|
len = sizeof(level_1->ControllerNameUnicodeString);
|
|
}
|
|
|
|
RtlCopyMemory(&level_1->ControllerNameUnicodeString[0],
|
|
deviceExtensionUsbd->DeviceLinkUnicodeString.Buffer,
|
|
len);
|
|
|
|
ntStatus = STATUS_SUCCESS;
|
|
} else {
|
|
ntStatus = STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBD_BusGetBusInformation(
|
|
IN PVOID BusContext,
|
|
IN ULONG Level,
|
|
IN PUSB_DEVICE_HANDLE DeviceHandle,
|
|
IN OUT PVOID DeviceInformationBuffer,
|
|
IN OUT PULONG DeviceInformationBufferLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
TEST_TRAP();
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
USBD_GetBusInterfaceHub(
|
|
IN PDEVICE_OBJECT RootHubPdo,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return the Hub Bus Interface to the caller
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
PIO_STACK_LOCATION irpStack;
|
|
NTSTATUS ntStatus;
|
|
USHORT requestedSize, requestedVersion;
|
|
|
|
PAGED_CODE();
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
requestedSize = irpStack->Parameters.QueryInterface.Size;
|
|
requestedVersion = irpStack->Parameters.QueryInterface.Version;
|
|
|
|
// assume success
|
|
ntStatus = STATUS_SUCCESS;
|
|
|
|
|
|
if (requestedVersion >= USB_BUSIF_HUB_VERSION_0) {
|
|
|
|
PUSB_BUS_INTERFACE_HUB_V0 busInterface0;
|
|
|
|
busInterface0 = (PUSB_BUS_INTERFACE_HUB_V0)
|
|
irpStack->Parameters.QueryInterface.Interface;
|
|
|
|
busInterface0->BusContext =
|
|
RootHubPdo;
|
|
busInterface0->InterfaceReference =
|
|
USBD_BusInterfaceReference;
|
|
busInterface0->InterfaceDereference =
|
|
USBD_BusInterfaceDereference;
|
|
|
|
busInterface0->Size = sizeof(USB_BUS_INTERFACE_HUB_V0);
|
|
busInterface0->Version = USB_BUSIF_HUB_VERSION_0;
|
|
}
|
|
|
|
if (requestedVersion >= USB_BUSIF_HUB_VERSION_1) {
|
|
|
|
PUSB_BUS_INTERFACE_HUB_V1 busInterface1;
|
|
|
|
busInterface1 = (PUSB_BUS_INTERFACE_HUB_V1)
|
|
irpStack->Parameters.QueryInterface.Interface;
|
|
|
|
busInterface1->CreateUsbDevice =
|
|
USBD_BusCreateDevice;
|
|
busInterface1->InitializeUsbDevice =
|
|
USBD_BusInitializeDevice;
|
|
busInterface1->GetUsbDescriptors =
|
|
USBD_BusGetUsbDescriptors;
|
|
busInterface1->RemoveUsbDevice =
|
|
USBD_BusRemoveDevice;
|
|
busInterface1->RestoreUsbDevice =
|
|
USBD_BusRestoreDevice;
|
|
busInterface1->GetPortHackFlags =
|
|
USBD_BusGetUsbPortHackFlags;
|
|
busInterface1->QueryDeviceInformation =
|
|
USBD_BusQueryDeviceInformation;
|
|
|
|
busInterface1->Size = sizeof(USB_BUS_INTERFACE_HUB_V1);
|
|
busInterface1->Version = USB_BUSIF_HUB_VERSION_1;
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBD_GetBusInterfaceUSBDI(
|
|
IN PDEVICE_OBJECT RootHubPdo,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return the Hub Bus Interface to the caller
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
PIO_STACK_LOCATION irpStack;
|
|
NTSTATUS ntStatus;
|
|
USHORT requestedSize, requestedVersion;
|
|
|
|
PAGED_CODE();
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
requestedSize = irpStack->Parameters.QueryInterface.Size;
|
|
requestedVersion = irpStack->Parameters.QueryInterface.Version;
|
|
|
|
// assume success
|
|
ntStatus = STATUS_SUCCESS;
|
|
|
|
if (requestedVersion >= USB_BUSIF_USBDI_VERSION_0) {
|
|
|
|
PUSB_BUS_INTERFACE_USBDI_V0 busInterface0;
|
|
|
|
busInterface0 = (PUSB_BUS_INTERFACE_USBDI_V0)
|
|
irpStack->Parameters.QueryInterface.Interface;
|
|
|
|
busInterface0->BusContext =
|
|
RootHubPdo;
|
|
busInterface0->InterfaceReference =
|
|
USBD_BusInterfaceReference;
|
|
busInterface0->InterfaceDereference =
|
|
USBD_BusInterfaceDereference;
|
|
|
|
busInterface0->GetUSBDIVersion =
|
|
USBD_BusGetUSBDIVersion;
|
|
busInterface0->QueryBusTime =
|
|
USBD_BusQueryBusTime;
|
|
busInterface0->SubmitIsoOutUrb =
|
|
USBD_BusSubmitIsoOutUrb;
|
|
busInterface0->QueryBusInformation =
|
|
USBD_BusQueryBusInformation;
|
|
|
|
|
|
busInterface0->Size = sizeof(USB_BUS_INTERFACE_USBDI_V0);
|
|
busInterface0->Version = USB_BUSIF_USBDI_VERSION_0;
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBD_GetBusInterface(
|
|
IN PDEVICE_OBJECT RootHubPdo,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return the Hub Bus Interface to the caller
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
{
|
|
PIO_STACK_LOCATION irpStack;
|
|
NTSTATUS ntStatus;
|
|
USHORT requestedSize, requestedVersion;
|
|
|
|
PAGED_CODE();
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
requestedSize = irpStack->Parameters.QueryInterface.Size;
|
|
requestedVersion = irpStack->Parameters.QueryInterface.Version;
|
|
|
|
// USBPORT_KdPrint((1, "'USBPORT_GetBusInterface - Requested version = %d\n",
|
|
// requestedVersion));
|
|
// USBPORT_KdPrint((1, "'USBPORT_GetBusInterface - Requested size = %d\n",
|
|
// requestedSize));
|
|
// USBPORT_KdPrint((1, "'USBPORT_GetBusInterface - interface data = %x\n",
|
|
// irpStack->Parameters.QueryInterface.InterfaceSpecificData));
|
|
|
|
|
|
// Initialize ntStatus as IRP status, because we're not supposed to
|
|
// touch the IRP status for interfaces that we do not support.
|
|
// (USBD_PdoPnP sets IRP status to ntStatus on exit.)
|
|
ntStatus = Irp->IoStatus.Status;
|
|
|
|
// validate version, size and GUID
|
|
if (RtlCompareMemory(irpStack->Parameters.QueryInterface.InterfaceType,
|
|
&USB_BUS_INTERFACE_HUB_GUID,
|
|
sizeof(GUID)) == sizeof(GUID)) {
|
|
|
|
ntStatus = USBD_GetBusInterfaceHub(RootHubPdo,
|
|
Irp);
|
|
|
|
} else if (RtlCompareMemory(irpStack->Parameters.QueryInterface.InterfaceType,
|
|
&USB_BUS_INTERFACE_USBDI_GUID,
|
|
sizeof(GUID)) == sizeof(GUID)) {
|
|
|
|
ntStatus = USBD_GetBusInterfaceUSBDI(RootHubPdo,
|
|
Irp);
|
|
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
#endif // USBD_DRIVER
|
|
|