mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
908 lines
28 KiB
C
908 lines
28 KiB
C
/*
|
|
* PROJECT: ReactOS USB Port Driver
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
|
* PURPOSE: USBPort interface functions
|
|
* COPYRIGHT: Copyright 2017 Vadim Galyant <vgal@rambler.ru>
|
|
*/
|
|
|
|
#include "usbport.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
VOID
|
|
USB_BUSIFFN
|
|
USBI_InterfaceReference(IN PVOID BusContext)
|
|
{
|
|
DPRINT("USBI_InterfaceReference \n");
|
|
}
|
|
|
|
VOID
|
|
USB_BUSIFFN
|
|
USBI_InterfaceDereference(IN PVOID BusContext)
|
|
{
|
|
DPRINT("USBI_InterfaceDereference \n");
|
|
}
|
|
|
|
/* USB port driver Interface functions */
|
|
|
|
NTSTATUS
|
|
USB_BUSIFFN
|
|
USBHI_CreateUsbDevice(IN PVOID BusContext,
|
|
IN OUT PUSB_DEVICE_HANDLE *UsbdDeviceHandle,
|
|
IN PUSB_DEVICE_HANDLE UsbdHubDeviceHandle,
|
|
IN USHORT PortStatus,
|
|
IN USHORT PortNumber)
|
|
{
|
|
PDEVICE_OBJECT PdoDevice;
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
PUSB_DEVICE_HANDLE deviceHandle = NULL;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("USBHI_CreateUsbDevice: ... \n");
|
|
|
|
PdoDevice = BusContext;
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
|
|
Status = USBPORT_CreateDevice(&deviceHandle,
|
|
PdoExtension->FdoDevice,
|
|
(PUSBPORT_DEVICE_HANDLE)UsbdHubDeviceHandle,
|
|
PortStatus,
|
|
PortNumber);
|
|
|
|
*UsbdDeviceHandle = deviceHandle;
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
USB_BUSIFFN
|
|
USBHI_InitializeUsbDevice(IN PVOID BusContext,
|
|
OUT PUSB_DEVICE_HANDLE UsbdDeviceHandle)
|
|
{
|
|
PDEVICE_OBJECT PdoDevice;
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
|
|
DPRINT("USBHI_InitializeUsbDevice \n");
|
|
|
|
PdoDevice = BusContext;
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
|
|
return USBPORT_InitializeDevice((PUSBPORT_DEVICE_HANDLE)UsbdDeviceHandle,
|
|
PdoExtension->FdoDevice);
|
|
}
|
|
|
|
NTSTATUS
|
|
USB_BUSIFFN
|
|
USBHI_GetUsbDescriptors(IN PVOID BusContext,
|
|
IN PUSB_DEVICE_HANDLE UsbdDeviceHandle,
|
|
IN PUCHAR DeviceDescBuffer,
|
|
IN PULONG DeviceDescBufferLen,
|
|
IN PUCHAR ConfigDescBuffer,
|
|
IN PULONG ConfigDescBufferLen)
|
|
{
|
|
PDEVICE_OBJECT PdoDevice;
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
PUSBPORT_DEVICE_HANDLE DeviceHandle;
|
|
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("USBHI_GetUsbDescriptors ...\n");
|
|
|
|
PdoDevice = BusContext;
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
DeviceHandle = (PUSBPORT_DEVICE_HANDLE)UsbdDeviceHandle;
|
|
|
|
if (DeviceDescBuffer && *DeviceDescBufferLen)
|
|
{
|
|
if (*DeviceDescBufferLen > sizeof(USB_DEVICE_DESCRIPTOR))
|
|
*DeviceDescBufferLen = sizeof(USB_DEVICE_DESCRIPTOR);
|
|
|
|
RtlCopyMemory(DeviceDescBuffer,
|
|
&DeviceHandle->DeviceDescriptor,
|
|
*DeviceDescBufferLen);
|
|
}
|
|
|
|
Status = USBPORT_GetUsbDescriptor(DeviceHandle,
|
|
PdoExtension->FdoDevice,
|
|
USB_CONFIGURATION_DESCRIPTOR_TYPE,
|
|
ConfigDescBuffer,
|
|
ConfigDescBufferLen);
|
|
|
|
USBPORT_DumpingDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)DeviceDescBuffer);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
USB_BUSIFFN
|
|
USBHI_RemoveUsbDevice(IN PVOID BusContext,
|
|
IN OUT PUSB_DEVICE_HANDLE UsbdDeviceHandle,
|
|
IN ULONG Flags)
|
|
{
|
|
PDEVICE_OBJECT PdoDevice;
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
|
|
DPRINT("USBHI_RemoveUsbDevice: UsbdDeviceHandle - %p, Flags - %x\n",
|
|
UsbdDeviceHandle,
|
|
Flags);
|
|
|
|
PdoDevice = BusContext;
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
|
|
return USBPORT_RemoveDevice(PdoExtension->FdoDevice,
|
|
(PUSBPORT_DEVICE_HANDLE)UsbdDeviceHandle,
|
|
Flags);
|
|
}
|
|
|
|
NTSTATUS
|
|
USB_BUSIFFN
|
|
USBHI_RestoreUsbDevice(IN PVOID BusContext,
|
|
OUT PUSB_DEVICE_HANDLE OldUsbdDeviceHandle,
|
|
OUT PUSB_DEVICE_HANDLE NewUsbdDeviceHandle)
|
|
{
|
|
PDEVICE_OBJECT PdoDevice;
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
|
|
DPRINT("USBHI_RestoreUsbDevice: OldUsbdDeviceHandle - %p, NewUsbdDeviceHandle - %x\n",
|
|
OldUsbdDeviceHandle,
|
|
NewUsbdDeviceHandle);
|
|
|
|
PdoDevice = BusContext;
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
|
|
return USBPORT_RestoreDevice(PdoExtension->FdoDevice,
|
|
(PUSBPORT_DEVICE_HANDLE)OldUsbdDeviceHandle,
|
|
(PUSBPORT_DEVICE_HANDLE)NewUsbdDeviceHandle);
|
|
}
|
|
|
|
NTSTATUS
|
|
USB_BUSIFFN
|
|
USBHI_QueryDeviceInformation(IN PVOID BusContext,
|
|
IN PUSB_DEVICE_HANDLE UsbdDeviceHandle,
|
|
OUT PVOID DeviceInfoBuffer,
|
|
IN ULONG DeviceInfoBufferLen,
|
|
OUT PULONG LenDataReturned)
|
|
{
|
|
PUSB_DEVICE_INFORMATION_0 DeviceInfo;
|
|
PUSBPORT_CONFIGURATION_HANDLE ConfigHandle;
|
|
PLIST_ENTRY InterfaceEntry;
|
|
PUSBPORT_DEVICE_HANDLE DeviceHandle;
|
|
ULONG NumberOfOpenPipes = 0;
|
|
PUSB_PIPE_INFORMATION_0 PipeInfo;
|
|
PUSBPORT_PIPE_HANDLE PipeHandle;
|
|
PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
|
|
ULONG ActualLength;
|
|
ULONG ix;
|
|
|
|
DPRINT("USBHI_QueryDeviceInformation: ... \n");
|
|
|
|
*LenDataReturned = 0;
|
|
|
|
if (DeviceInfoBufferLen < sizeof(USB_LEVEL_INFORMATION))
|
|
{
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
DeviceInfo = DeviceInfoBuffer;
|
|
|
|
if (DeviceInfo->InformationLevel > 0)
|
|
{
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
DeviceHandle = UsbdDeviceHandle;
|
|
ConfigHandle = DeviceHandle->ConfigHandle;
|
|
|
|
if (ConfigHandle)
|
|
{
|
|
InterfaceEntry = ConfigHandle->InterfaceHandleList.Flink;
|
|
|
|
while (InterfaceEntry &&
|
|
InterfaceEntry != &ConfigHandle->InterfaceHandleList)
|
|
{
|
|
InterfaceHandle = CONTAINING_RECORD(InterfaceEntry,
|
|
USBPORT_INTERFACE_HANDLE,
|
|
InterfaceLink);
|
|
|
|
NumberOfOpenPipes += InterfaceHandle->InterfaceDescriptor.bNumEndpoints;
|
|
|
|
InterfaceEntry = InterfaceEntry->Flink;
|
|
}
|
|
}
|
|
|
|
ActualLength = sizeof(USB_DEVICE_INFORMATION_0) +
|
|
(NumberOfOpenPipes - 1) * sizeof(USB_PIPE_INFORMATION_0);
|
|
|
|
if (DeviceInfoBufferLen < ActualLength)
|
|
{
|
|
DeviceInfo->ActualLength = ActualLength;
|
|
*LenDataReturned = sizeof(USB_LEVEL_INFORMATION);
|
|
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
RtlZeroMemory(DeviceInfo, ActualLength);
|
|
|
|
DeviceInfo->InformationLevel = 0;
|
|
DeviceInfo->ActualLength = ActualLength;
|
|
DeviceInfo->DeviceAddress = DeviceHandle->DeviceAddress;
|
|
DeviceInfo->NumberOfOpenPipes = NumberOfOpenPipes;
|
|
DeviceInfo->DeviceSpeed = DeviceHandle->DeviceSpeed;
|
|
|
|
RtlCopyMemory(&DeviceInfo->DeviceDescriptor,
|
|
&DeviceHandle->DeviceDescriptor,
|
|
sizeof(USB_DEVICE_DESCRIPTOR));
|
|
|
|
USBPORT_DumpingDeviceDescriptor(&DeviceInfo->DeviceDescriptor);
|
|
|
|
if (DeviceHandle->DeviceSpeed == UsbFullSpeed ||
|
|
DeviceHandle->DeviceSpeed == UsbLowSpeed)
|
|
{
|
|
DeviceInfo->DeviceType = Usb11Device;
|
|
}
|
|
else if (DeviceHandle->DeviceSpeed == UsbHighSpeed)
|
|
{
|
|
DeviceInfo->DeviceType = Usb20Device;
|
|
}
|
|
|
|
DeviceInfo->CurrentConfigurationValue = 0;
|
|
|
|
if (!ConfigHandle)
|
|
{
|
|
*LenDataReturned = ActualLength;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
DeviceInfo->CurrentConfigurationValue =
|
|
ConfigHandle->ConfigurationDescriptor->bConfigurationValue;
|
|
|
|
InterfaceEntry = ConfigHandle->InterfaceHandleList.Flink;
|
|
|
|
while (InterfaceEntry &&
|
|
InterfaceEntry != &ConfigHandle->InterfaceHandleList)
|
|
{
|
|
InterfaceHandle = CONTAINING_RECORD(InterfaceEntry,
|
|
USBPORT_INTERFACE_HANDLE,
|
|
InterfaceLink);
|
|
|
|
if (InterfaceHandle->InterfaceDescriptor.bNumEndpoints > 0)
|
|
{
|
|
PipeInfo = &DeviceInfo->PipeList[0];
|
|
PipeHandle = &InterfaceHandle->PipeHandle[0];
|
|
|
|
for (ix = 0;
|
|
ix < InterfaceHandle->InterfaceDescriptor.bNumEndpoints;
|
|
ix++)
|
|
{
|
|
if (PipeHandle->Flags & PIPE_HANDLE_FLAG_NULL_PACKET_SIZE)
|
|
{
|
|
PipeInfo->ScheduleOffset = 1;
|
|
}
|
|
else
|
|
{
|
|
PipeInfo->ScheduleOffset =
|
|
PipeHandle->Endpoint->EndpointProperties.ScheduleOffset;
|
|
}
|
|
|
|
RtlCopyMemory(&PipeInfo->EndpointDescriptor,
|
|
&PipeHandle->EndpointDescriptor,
|
|
sizeof(USB_ENDPOINT_DESCRIPTOR));
|
|
|
|
PipeInfo += 1;
|
|
PipeHandle += 1;
|
|
}
|
|
}
|
|
|
|
InterfaceEntry = InterfaceEntry->Flink;
|
|
}
|
|
|
|
*LenDataReturned = ActualLength;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
USB_BUSIFFN
|
|
USBHI_GetControllerInformation(IN PVOID BusContext,
|
|
OUT PVOID ControllerInfoBuffer,
|
|
IN ULONG ControllerInfoBufferLen,
|
|
OUT PULONG LenDataReturned)
|
|
{
|
|
PDEVICE_OBJECT PdoDevice;
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
PDEVICE_OBJECT FdoDevice;
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
PUSB_CONTROLLER_INFORMATION_0 InfoBuffer;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("USBHI_GetControllerInformation: ControllerInfoBufferLen - %x\n",
|
|
ControllerInfoBufferLen);
|
|
|
|
PdoDevice = BusContext;
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
FdoDevice = PdoExtension->FdoDevice;
|
|
FdoExtension = FdoDevice->DeviceExtension;
|
|
|
|
InfoBuffer = ControllerInfoBuffer;
|
|
|
|
*LenDataReturned = 0;
|
|
|
|
if (ControllerInfoBufferLen < sizeof(USB_LEVEL_INFORMATION))
|
|
{
|
|
Status = STATUS_BUFFER_TOO_SMALL;
|
|
return Status;
|
|
}
|
|
|
|
*LenDataReturned = sizeof(USB_LEVEL_INFORMATION);
|
|
|
|
if (InfoBuffer->InformationLevel > 0)
|
|
{
|
|
Status = STATUS_NOT_SUPPORTED;
|
|
return Status;
|
|
}
|
|
|
|
InfoBuffer->ActualLength = sizeof(USB_CONTROLLER_INFORMATION_0);
|
|
|
|
if (ControllerInfoBufferLen >= sizeof(USB_CONTROLLER_INFORMATION_0))
|
|
{
|
|
InfoBuffer->SelectiveSuspendEnabled =
|
|
(FdoExtension->Flags & USBPORT_FLAG_SELECTIVE_SUSPEND) ==
|
|
USBPORT_FLAG_SELECTIVE_SUSPEND;
|
|
}
|
|
|
|
*LenDataReturned = sizeof(USB_CONTROLLER_INFORMATION_0);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
USB_BUSIFFN
|
|
USBHI_ControllerSelectiveSuspend(IN PVOID BusContext,
|
|
IN BOOLEAN Enable)
|
|
{
|
|
PDEVICE_OBJECT PdoDevice;
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
PDEVICE_OBJECT FdoDevice;
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
ULONG Flags;
|
|
ULONG HcDisable;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("USBHI_ControllerSelectiveSuspend: Enable - %x\n", Enable);
|
|
|
|
PdoDevice = BusContext;
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
FdoDevice = PdoExtension->FdoDevice;
|
|
FdoExtension = FdoDevice->DeviceExtension;
|
|
|
|
Flags = FdoExtension->Flags;
|
|
|
|
if (Flags & USBPORT_FLAG_BIOS_DISABLE_SS)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
if (Enable)
|
|
{
|
|
FdoExtension->Flags |= USBPORT_FLAG_SELECTIVE_SUSPEND;
|
|
HcDisable = 0;
|
|
}
|
|
else
|
|
{
|
|
FdoExtension->Flags &= ~USBPORT_FLAG_SELECTIVE_SUSPEND;
|
|
HcDisable = 1;
|
|
}
|
|
|
|
Status = USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
|
|
TRUE,
|
|
REG_DWORD,
|
|
L"HcDisableSelectiveSuspend",
|
|
&HcDisable,
|
|
sizeof(HcDisable));
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (Enable)
|
|
FdoExtension->Flags |= USBPORT_FLAG_SELECTIVE_SUSPEND;
|
|
else
|
|
FdoExtension->Flags &= ~USBPORT_FLAG_SELECTIVE_SUSPEND;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
USB_BUSIFFN
|
|
USBHI_GetExtendedHubInformation(IN PVOID BusContext,
|
|
IN PDEVICE_OBJECT HubPhysicalDeviceObject,
|
|
IN OUT PVOID HubInformationBuffer,
|
|
IN ULONG HubInfoLen,
|
|
IN OUT PULONG LenDataReturned)
|
|
{
|
|
PDEVICE_OBJECT PdoDevice;
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
PDEVICE_OBJECT FdoDevice;
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
PUSBPORT_REGISTRATION_PACKET Packet;
|
|
ULONG NumPorts;
|
|
ULONG ix;
|
|
PUSB_EXTHUB_INFORMATION_0 HubInfoBuffer;
|
|
USB_PORT_STATUS_AND_CHANGE PortStatus;
|
|
ULONG PortAttrX;
|
|
|
|
DPRINT("USBHI_GetExtendedHubInformation: ... \n");
|
|
|
|
PdoDevice = BusContext;
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
FdoDevice = PdoExtension->FdoDevice;
|
|
FdoExtension = FdoDevice->DeviceExtension;
|
|
Packet = &FdoExtension->MiniPortInterface->Packet;
|
|
|
|
HubInfoBuffer = HubInformationBuffer;
|
|
PortStatus.AsUlong32 = 0;
|
|
|
|
if (HubPhysicalDeviceObject != PdoDevice)
|
|
{
|
|
*LenDataReturned = 0;
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
if (HubInfoLen < sizeof(USB_EXTHUB_INFORMATION_0))
|
|
{
|
|
*LenDataReturned = 0;
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
NumPorts = PdoExtension->RootHubDescriptors->Descriptor.bNumberOfPorts;
|
|
HubInfoBuffer->NumberOfPorts = NumPorts;
|
|
|
|
if (NumPorts == 0)
|
|
{
|
|
*LenDataReturned = sizeof(USB_EXTHUB_INFORMATION_0);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
for (ix = 0; ix < HubInfoBuffer->NumberOfPorts; ++ix)
|
|
{
|
|
HubInfoBuffer->Port[ix].PhysicalPortNumber = ix + 1;
|
|
HubInfoBuffer->Port[ix].PortLabelNumber = ix;
|
|
HubInfoBuffer->Port[ix].VidOverride = 0;
|
|
HubInfoBuffer->Port[ix].PidOverride = 0;
|
|
HubInfoBuffer->Port[ix].PortAttributes = 0;
|
|
|
|
if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
|
|
{
|
|
HubInfoBuffer->Port[ix].PortAttributes = USB_PORTATTR_SHARED_USB2;
|
|
|
|
Packet->RH_GetPortStatus(FdoExtension->MiniPortExt,
|
|
ix,
|
|
&PortStatus);
|
|
|
|
if (PortStatus.PortStatus.Usb20PortStatus.AsUshort16 & 0x8000)
|
|
{
|
|
HubInfoBuffer->Port[ix].PortAttributes |= USB_PORTATTR_OWNED_BY_CC;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!(FdoExtension->Flags & USBPORT_FLAG_COMPANION_HC))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (USBPORT_FindUSB2Controller(FdoDevice))
|
|
{
|
|
HubInfoBuffer->Port[ix].PortAttributes |= USB_PORTATTR_NO_OVERCURRENT_UI;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (ix = 0; ix < HubInfoBuffer->NumberOfPorts; ++ix)
|
|
{
|
|
PortAttrX = 0;
|
|
|
|
USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
|
|
FdoExtension->CommonExtension.LowerPdoDevice,
|
|
FALSE,
|
|
L"PortAttrX",
|
|
sizeof(L"PortAttrX"),
|
|
&PortAttrX,
|
|
sizeof(PortAttrX));
|
|
|
|
HubInfoBuffer->Port[ix].PortAttributes |= PortAttrX;
|
|
}
|
|
|
|
*LenDataReturned = sizeof(USB_EXTHUB_INFORMATION_0);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
USB_BUSIFFN
|
|
USBHI_GetRootHubSymbolicName(IN PVOID BusContext,
|
|
IN OUT PVOID HubInfoBuffer,
|
|
IN ULONG HubInfoBufferLen,
|
|
OUT PULONG HubNameActualLen)
|
|
{
|
|
PDEVICE_OBJECT PdoDevice;
|
|
UNICODE_STRING HubName;
|
|
PUNICODE_STRING InfoBuffer;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("USBHI_GetRootHubSymbolicName: ... \n");
|
|
|
|
PdoDevice = BusContext;
|
|
|
|
Status = USBPORT_GetSymbolicName(PdoDevice, &HubName);
|
|
|
|
if (HubInfoBufferLen < HubName.Length)
|
|
{
|
|
InfoBuffer = HubInfoBuffer;
|
|
InfoBuffer->Length = 0;
|
|
}
|
|
else
|
|
{
|
|
RtlCopyMemory(HubInfoBuffer, HubName.Buffer, HubName.Length);
|
|
}
|
|
|
|
*HubNameActualLen = HubName.Length;
|
|
|
|
if (NT_SUCCESS(Status))
|
|
RtlFreeUnicodeString(&HubName);
|
|
|
|
return Status;
|
|
}
|
|
|
|
PVOID
|
|
USB_BUSIFFN
|
|
USBHI_GetDeviceBusContext(IN PVOID BusContext,
|
|
IN PVOID DeviceHandle)
|
|
{
|
|
DPRINT1("USBHI_GetDeviceBusContext: UNIMPLEMENTED. FIXME. \n");
|
|
return NULL;
|
|
}
|
|
|
|
NTSTATUS
|
|
USB_BUSIFFN
|
|
USBHI_Initialize20Hub(IN PVOID BusContext,
|
|
IN PUSB_DEVICE_HANDLE UsbdHubDeviceHandle,
|
|
IN ULONG TtCount)
|
|
{
|
|
PDEVICE_OBJECT PdoDevice;
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
|
|
DPRINT("USBHI_Initialize20Hub: UsbdHubDeviceHandle - %p, TtCount - %x\n",
|
|
UsbdHubDeviceHandle,
|
|
TtCount);
|
|
|
|
PdoDevice = BusContext;
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
|
|
return USBPORT_Initialize20Hub(PdoExtension->FdoDevice,
|
|
(PUSBPORT_DEVICE_HANDLE)UsbdHubDeviceHandle,
|
|
TtCount);
|
|
}
|
|
|
|
NTSTATUS
|
|
USB_BUSIFFN
|
|
USBHI_RootHubInitNotification(IN PVOID BusContext,
|
|
IN PVOID CallbackContext,
|
|
IN PRH_INIT_CALLBACK CallbackFunction)
|
|
{
|
|
PDEVICE_OBJECT PdoDevice;
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
PDEVICE_OBJECT FdoDevice;
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
KIRQL OldIrql;
|
|
|
|
DPRINT("USBHI_RootHubInitNotification \n");
|
|
|
|
PdoDevice = BusContext;
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
FdoDevice = PdoExtension->FdoDevice;
|
|
FdoExtension = FdoDevice->DeviceExtension;
|
|
|
|
KeAcquireSpinLock(&FdoExtension->RootHubCallbackSpinLock, &OldIrql);
|
|
PdoExtension->RootHubInitContext = CallbackContext;
|
|
PdoExtension->RootHubInitCallback = CallbackFunction;
|
|
KeReleaseSpinLock(&FdoExtension->RootHubCallbackSpinLock, OldIrql);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
USB_BUSIFFN
|
|
USBHI_FlushTransfers(IN PVOID BusContext,
|
|
OUT PUSB_DEVICE_HANDLE UsbdDeviceHandle)
|
|
{
|
|
PDEVICE_OBJECT PdoDevice;
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
|
|
DPRINT("USBHI_FlushTransfers: ... \n");
|
|
|
|
PdoDevice = BusContext;
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
|
|
USBPORT_BadRequestFlush(PdoExtension->FdoDevice);
|
|
}
|
|
|
|
VOID
|
|
USB_BUSIFFN
|
|
USBHI_SetDeviceHandleData(IN PVOID BusContext,
|
|
IN PVOID DeviceHandle,
|
|
IN PDEVICE_OBJECT UsbDevicePdo)
|
|
{
|
|
DPRINT1("USBHI_SetDeviceHandleData: UNIMPLEMENTED. FIXME. \n");
|
|
}
|
|
|
|
/* USB bus driver Interface functions */
|
|
|
|
VOID
|
|
USB_BUSIFFN
|
|
USBDI_GetUSBDIVersion(IN PVOID BusContext,
|
|
OUT PUSBD_VERSION_INFORMATION VersionInfo,
|
|
OUT PULONG HcdCapabilities)
|
|
{
|
|
DPRINT1("USBDI_GetUSBDIVersion: UNIMPLEMENTED. FIXME. \n");
|
|
}
|
|
|
|
NTSTATUS
|
|
USB_BUSIFFN
|
|
USBDI_QueryBusTime(IN PVOID BusContext,
|
|
OUT PULONG CurrentFrame)
|
|
{
|
|
DPRINT1("USBDI_QueryBusTime: UNIMPLEMENTED. FIXME. \n");
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
USB_BUSIFFN
|
|
USBDI_SubmitIsoOutUrb(IN PVOID BusContext,
|
|
IN PURB Urb)
|
|
{
|
|
DPRINT1("USBDI_SubmitIsoOutUrb: UNIMPLEMENTED. FIXME. \n");
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
USB_BUSIFFN
|
|
USBDI_QueryBusInformation(IN PVOID BusContext,
|
|
IN ULONG Level,
|
|
OUT PVOID BusInfoBuffer,
|
|
OUT PULONG BusInfoBufferLen,
|
|
OUT PULONG BusInfoActualLen)
|
|
{
|
|
PDEVICE_OBJECT PdoDevice;
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
PDEVICE_OBJECT FdoDevice;
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
SIZE_T Length;
|
|
PUSB_BUS_INFORMATION_LEVEL_1 Buffer1;
|
|
|
|
DPRINT("USBDI_QueryBusInformation: Level - %p\n", Level);
|
|
|
|
if ((Level != 0) || (Level != 1))
|
|
{
|
|
DPRINT1("USBDI_QueryBusInformation: Level should be 0 or 1\n");
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
PdoDevice = BusContext;
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
FdoDevice = PdoExtension->FdoDevice;
|
|
FdoExtension = FdoDevice->DeviceExtension;
|
|
|
|
if (Level == 0)
|
|
{
|
|
if (BusInfoActualLen)
|
|
*BusInfoActualLen = sizeof(USB_BUS_INFORMATION_LEVEL_0);
|
|
|
|
if (*BusInfoBufferLen < sizeof(USB_BUS_INFORMATION_LEVEL_0))
|
|
{
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
*BusInfoBufferLen = sizeof(USB_BUS_INFORMATION_LEVEL_0);
|
|
|
|
//Buffer0 = BusInfoBuffer;
|
|
DPRINT1("USBDI_QueryBusInformation: LEVEL_0 UNIMPLEMENTED. FIXME\n");
|
|
//Buffer0->TotalBandwidth = USBPORT_GetTotalBandwidth();
|
|
//Buffer0->ConsumedBandwidth = USBPORT_GetAllocatedBandwidth();
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
if (Level == 1)
|
|
{
|
|
Length = sizeof(USB_BUS_INFORMATION_LEVEL_1) +
|
|
FdoExtension->CommonExtension.SymbolicLinkName.Length;
|
|
|
|
if (BusInfoActualLen)
|
|
*BusInfoActualLen = Length;
|
|
|
|
if (*BusInfoBufferLen < Length)
|
|
{
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
*BusInfoBufferLen = Length;
|
|
|
|
Buffer1 = BusInfoBuffer;
|
|
DPRINT1("USBDI_QueryBusInformation: LEVEL_1 UNIMPLEMENTED. FIXME\n");
|
|
//Buffer1->TotalBandwidth = USBPORT_GetTotalBandwidth();
|
|
//Buffer1->ConsumedBandwidth = USBPORT_GetAllocatedBandwidth();
|
|
Buffer1->ControllerNameLength = FdoExtension->CommonExtension.SymbolicLinkName.Length;
|
|
|
|
RtlCopyMemory(&Buffer1->ControllerNameUnicodeString,
|
|
FdoExtension->CommonExtension.SymbolicLinkName.Buffer,
|
|
FdoExtension->CommonExtension.SymbolicLinkName.Length);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
BOOLEAN
|
|
USB_BUSIFFN
|
|
USBDI_IsDeviceHighSpeed(IN PVOID BusContext)
|
|
{
|
|
PDEVICE_OBJECT PdoDevice;
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
PDEVICE_OBJECT FdoDevice;
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
PUSBPORT_REGISTRATION_PACKET Packet;
|
|
|
|
DPRINT("USBDI_IsDeviceHighSpeed: ... \n");
|
|
|
|
PdoDevice = BusContext;
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
FdoDevice = PdoExtension->FdoDevice;
|
|
FdoExtension = FdoDevice->DeviceExtension;
|
|
Packet = &FdoExtension->MiniPortInterface->Packet;
|
|
|
|
return (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2) != 0;
|
|
}
|
|
|
|
NTSTATUS
|
|
USB_BUSIFFN
|
|
USBDI_EnumLogEntry(IN PVOID BusContext,
|
|
IN ULONG DriverTag,
|
|
IN ULONG EnumTag,
|
|
IN ULONG P1,
|
|
IN ULONG P2)
|
|
{
|
|
DPRINT1("USBDI_EnumLogEntry: UNIMPLEMENTED. FIXME. \n");
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
USBPORT_PdoQueryInterface(IN PDEVICE_OBJECT FdoDevice,
|
|
IN PDEVICE_OBJECT PdoDevice,
|
|
IN PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub;
|
|
PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI;
|
|
UNICODE_STRING GuidBuffer;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("USBPORT_PdoQueryInterface: ... \n");
|
|
|
|
if (IsEqualGUIDAligned(IoStack->Parameters.QueryInterface.InterfaceType,
|
|
&USB_BUS_INTERFACE_HUB_GUID))
|
|
{
|
|
/* Get request parameters */
|
|
InterfaceHub = (PUSB_BUS_INTERFACE_HUB_V5)IoStack->Parameters.QueryInterface.Interface;
|
|
InterfaceHub->Version = IoStack->Parameters.QueryInterface.Version;
|
|
|
|
/* Check version */
|
|
if (IoStack->Parameters.QueryInterface.Version >= 6)
|
|
{
|
|
DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n",
|
|
IoStack->Parameters.QueryInterface.Version);
|
|
|
|
return STATUS_NOT_SUPPORTED; // Version not supported
|
|
}
|
|
|
|
/* Interface version 0 */
|
|
InterfaceHub->Size = IoStack->Parameters.QueryInterface.Size;
|
|
InterfaceHub->BusContext = PdoDevice;
|
|
|
|
InterfaceHub->InterfaceReference = USBI_InterfaceReference;
|
|
InterfaceHub->InterfaceDereference = USBI_InterfaceDereference;
|
|
|
|
/* Interface version 1 */
|
|
if (IoStack->Parameters.QueryInterface.Version >= 1)
|
|
{
|
|
InterfaceHub->CreateUsbDevice = USBHI_CreateUsbDevice;
|
|
InterfaceHub->InitializeUsbDevice = USBHI_InitializeUsbDevice;
|
|
InterfaceHub->GetUsbDescriptors = USBHI_GetUsbDescriptors;
|
|
InterfaceHub->RemoveUsbDevice = USBHI_RemoveUsbDevice;
|
|
InterfaceHub->RestoreUsbDevice = USBHI_RestoreUsbDevice;
|
|
InterfaceHub->QueryDeviceInformation = USBHI_QueryDeviceInformation;
|
|
}
|
|
|
|
/* Interface version 2 */
|
|
if (IoStack->Parameters.QueryInterface.Version >= 2)
|
|
{
|
|
InterfaceHub->GetControllerInformation = USBHI_GetControllerInformation;
|
|
InterfaceHub->ControllerSelectiveSuspend = USBHI_ControllerSelectiveSuspend;
|
|
InterfaceHub->GetExtendedHubInformation = USBHI_GetExtendedHubInformation;
|
|
InterfaceHub->GetRootHubSymbolicName = USBHI_GetRootHubSymbolicName;
|
|
InterfaceHub->GetDeviceBusContext = USBHI_GetDeviceBusContext;
|
|
InterfaceHub->Initialize20Hub = USBHI_Initialize20Hub;
|
|
}
|
|
|
|
/* Interface version 3 */
|
|
if (IoStack->Parameters.QueryInterface.Version >= 3)
|
|
InterfaceHub->RootHubInitNotification = USBHI_RootHubInitNotification;
|
|
|
|
/* Interface version 4 */
|
|
if (IoStack->Parameters.QueryInterface.Version >= 4)
|
|
InterfaceHub->FlushTransfers = USBHI_FlushTransfers;
|
|
|
|
/* Interface version 5 */
|
|
if (IoStack->Parameters.QueryInterface.Version >= 5)
|
|
InterfaceHub->SetDeviceHandleData = USBHI_SetDeviceHandleData;
|
|
|
|
/* Request completed */
|
|
return STATUS_SUCCESS;
|
|
}
|
|
else if (IsEqualGUIDAligned(IoStack->Parameters.QueryInterface.InterfaceType,
|
|
&USB_BUS_INTERFACE_USBDI_GUID))
|
|
{
|
|
/* Get request parameters */
|
|
InterfaceDI = (PUSB_BUS_INTERFACE_USBDI_V2)IoStack->Parameters.QueryInterface.Interface;
|
|
InterfaceDI->Version = IoStack->Parameters.QueryInterface.Version;
|
|
|
|
/* Check version */
|
|
if (IoStack->Parameters.QueryInterface.Version >= 3)
|
|
{
|
|
DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n",
|
|
IoStack->Parameters.QueryInterface.Version);
|
|
|
|
return STATUS_NOT_SUPPORTED; // Version not supported
|
|
}
|
|
|
|
/* Interface version 0 */
|
|
InterfaceDI->Size = IoStack->Parameters.QueryInterface.Size;
|
|
InterfaceDI->BusContext = PdoDevice;
|
|
InterfaceDI->InterfaceReference = USBI_InterfaceReference;
|
|
InterfaceDI->InterfaceDereference = USBI_InterfaceDereference;
|
|
InterfaceDI->GetUSBDIVersion = USBDI_GetUSBDIVersion;
|
|
InterfaceDI->QueryBusTime = USBDI_QueryBusTime;
|
|
InterfaceDI->SubmitIsoOutUrb = USBDI_SubmitIsoOutUrb;
|
|
InterfaceDI->QueryBusInformation = USBDI_QueryBusInformation;
|
|
|
|
/* Interface version 1 */
|
|
if (IoStack->Parameters.QueryInterface.Version >= 1)
|
|
InterfaceDI->IsDeviceHighSpeed = USBDI_IsDeviceHighSpeed;
|
|
|
|
/* Interface version 2 */
|
|
if (IoStack->Parameters.QueryInterface.Version >= 2)
|
|
InterfaceDI->EnumLogEntry = USBDI_EnumLogEntry;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
/* Convert GUID to string */
|
|
Status = RtlStringFromGUID(IoStack->Parameters.QueryInterface.InterfaceType,
|
|
&GuidBuffer);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Print interface */
|
|
DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n",
|
|
&GuidBuffer,
|
|
IoStack->Parameters.QueryInterface.Version);
|
|
|
|
RtlFreeUnicodeString(&GuidBuffer); // Free GUID buffer
|
|
}
|
|
}
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|