2013-01-04 11:47:19 +00:00
|
|
|
|
/*
|
2011-05-04 01:07:21 +00:00
|
|
|
|
* PROJECT: ReactOS Universal Serial Bus Hub Driver
|
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
|
|
|
* FILE: drivers/usb/usbhub/fdo.c
|
|
|
|
|
* PURPOSE: Handle FDO
|
|
|
|
|
* PROGRAMMERS:
|
|
|
|
|
* Michael Martin (michael.martin@reactos.org)
|
|
|
|
|
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "usbhub.h"
|
|
|
|
|
|
2014-01-03 17:45:05 +00:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
2013-12-21 19:15:13 +00:00
|
|
|
|
#define NDEBUG
|
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
2011-05-04 12:58:42 +00:00
|
|
|
|
NTSTATUS
|
|
|
|
|
QueryStatusChangeEndpoint(
|
|
|
|
|
IN PDEVICE_OBJECT DeviceObject);
|
|
|
|
|
|
2011-05-04 21:45:55 +00:00
|
|
|
|
NTSTATUS
|
|
|
|
|
CreateUsbChildDeviceObject(
|
|
|
|
|
IN PDEVICE_OBJECT UsbHubDeviceObject,
|
|
|
|
|
IN LONG PortId,
|
2012-02-03 11:29:03 +00:00
|
|
|
|
OUT PDEVICE_OBJECT *UsbChildDeviceObject,
|
|
|
|
|
IN ULONG PortStatus);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
|
2012-01-22 21:58:06 +00:00
|
|
|
|
NTSTATUS
|
|
|
|
|
DestroyUsbChildDeviceObject(
|
|
|
|
|
IN PDEVICE_OBJECT UsbHubDeviceObject,
|
|
|
|
|
IN LONG PortId);
|
|
|
|
|
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
|
GetPortStatusAndChange(
|
2011-05-04 12:58:42 +00:00
|
|
|
|
IN PDEVICE_OBJECT RootHubDeviceObject,
|
2011-05-04 01:07:21 +00:00
|
|
|
|
IN ULONG PortId,
|
2011-05-04 12:58:42 +00:00
|
|
|
|
OUT PPORT_STATUS_CHANGE StatusChange)
|
2011-05-04 01:07:21 +00:00
|
|
|
|
{
|
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
PURB Urb;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Allocate URB
|
|
|
|
|
//
|
|
|
|
|
Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
|
|
|
|
|
if (!Urb)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to allocate memory for URB!\n");
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Zero it
|
|
|
|
|
//
|
|
|
|
|
RtlZeroMemory(Urb, sizeof(URB));
|
|
|
|
|
|
|
|
|
|
//
|
2011-05-12 12:58:07 +00:00
|
|
|
|
// Initialize URB for getting Port Status
|
2011-05-04 01:07:21 +00:00
|
|
|
|
//
|
|
|
|
|
UsbBuildVendorRequest(Urb,
|
|
|
|
|
URB_FUNCTION_CLASS_OTHER,
|
|
|
|
|
sizeof(Urb->UrbControlVendorClassRequest),
|
|
|
|
|
USBD_TRANSFER_DIRECTION_OUT,
|
|
|
|
|
0,
|
|
|
|
|
USB_REQUEST_GET_STATUS,
|
|
|
|
|
0,
|
|
|
|
|
PortId,
|
2011-05-04 12:58:42 +00:00
|
|
|
|
StatusChange,
|
2011-05-04 01:07:21 +00:00
|
|
|
|
0,
|
|
|
|
|
sizeof(PORT_STATUS_CHANGE),
|
|
|
|
|
0);
|
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// FIXME: support usb hubs
|
|
|
|
|
Urb->UrbHeader.UsbdDeviceHandle = NULL;
|
|
|
|
|
|
|
|
|
|
|
2011-05-04 01:07:21 +00:00
|
|
|
|
//
|
|
|
|
|
// Query the Root Hub
|
|
|
|
|
//
|
2011-05-04 12:58:42 +00:00
|
|
|
|
Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Free URB
|
|
|
|
|
//
|
|
|
|
|
ExFreePool(Urb);
|
|
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
|
SetPortFeature(
|
2011-05-04 12:58:42 +00:00
|
|
|
|
IN PDEVICE_OBJECT RootHubDeviceObject,
|
|
|
|
|
IN ULONG PortId,
|
|
|
|
|
IN ULONG Feature)
|
2011-05-04 01:07:21 +00:00
|
|
|
|
{
|
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
PURB Urb;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Allocate URB
|
|
|
|
|
//
|
|
|
|
|
Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
|
|
|
|
|
if (!Urb)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to allocate memory for URB!\n");
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Zero it
|
|
|
|
|
//
|
|
|
|
|
RtlZeroMemory(Urb, sizeof(URB));
|
|
|
|
|
|
|
|
|
|
//
|
2011-05-12 12:58:07 +00:00
|
|
|
|
// Initialize URB for Clearing Port Reset
|
2011-05-04 01:07:21 +00:00
|
|
|
|
//
|
|
|
|
|
UsbBuildVendorRequest(Urb,
|
|
|
|
|
URB_FUNCTION_CLASS_OTHER,
|
|
|
|
|
sizeof(Urb->UrbControlVendorClassRequest),
|
|
|
|
|
USBD_TRANSFER_DIRECTION_IN,
|
|
|
|
|
0,
|
|
|
|
|
USB_REQUEST_SET_FEATURE,
|
|
|
|
|
Feature,
|
|
|
|
|
PortId,
|
|
|
|
|
NULL,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0);
|
2012-02-29 17:08:32 +00:00
|
|
|
|
|
|
|
|
|
// FIXME support usbhubs
|
|
|
|
|
Urb->UrbHeader.UsbdDeviceHandle = NULL;
|
|
|
|
|
|
2011-05-04 01:07:21 +00:00
|
|
|
|
//
|
|
|
|
|
// Query the Root Hub
|
|
|
|
|
//
|
2011-05-04 12:58:42 +00:00
|
|
|
|
Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Free URB
|
|
|
|
|
//
|
|
|
|
|
ExFreePool(Urb);
|
|
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
|
ClearPortFeature(
|
2011-05-04 12:58:42 +00:00
|
|
|
|
IN PDEVICE_OBJECT RootHubDeviceObject,
|
|
|
|
|
IN ULONG PortId,
|
|
|
|
|
IN ULONG Feature)
|
2011-05-04 01:07:21 +00:00
|
|
|
|
{
|
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
PURB Urb;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Allocate a URB
|
|
|
|
|
//
|
|
|
|
|
Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
|
|
|
|
|
if (!Urb)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to allocate memory for URB!\n");
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Zero it
|
|
|
|
|
//
|
|
|
|
|
RtlZeroMemory(Urb, sizeof(URB));
|
|
|
|
|
|
|
|
|
|
//
|
2011-05-12 12:58:07 +00:00
|
|
|
|
// Initialize URB for Clearing Port Reset
|
2011-05-04 01:07:21 +00:00
|
|
|
|
//
|
|
|
|
|
UsbBuildVendorRequest(Urb,
|
|
|
|
|
URB_FUNCTION_CLASS_OTHER,
|
|
|
|
|
sizeof(Urb->UrbControlVendorClassRequest),
|
|
|
|
|
USBD_TRANSFER_DIRECTION_IN,
|
|
|
|
|
0,
|
|
|
|
|
USB_REQUEST_CLEAR_FEATURE,
|
|
|
|
|
Feature,
|
|
|
|
|
PortId,
|
|
|
|
|
NULL,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0);
|
2012-02-29 17:08:32 +00:00
|
|
|
|
|
|
|
|
|
// FIXME: support usb hubs
|
|
|
|
|
Urb->UrbHeader.UsbdDeviceHandle = NULL;
|
|
|
|
|
|
2011-05-04 01:07:21 +00:00
|
|
|
|
//
|
|
|
|
|
// Query the Root Hub
|
|
|
|
|
//
|
2011-05-04 12:58:42 +00:00
|
|
|
|
Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Free URB
|
|
|
|
|
//
|
|
|
|
|
ExFreePool(Urb);
|
|
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-04 12:58:42 +00:00
|
|
|
|
VOID NTAPI
|
|
|
|
|
DeviceStatusChangeThread(
|
|
|
|
|
IN PVOID Context)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS Status;
|
2011-05-07 14:49:02 +00:00
|
|
|
|
PDEVICE_OBJECT DeviceObject, RootHubDeviceObject;
|
2011-05-04 12:58:42 +00:00
|
|
|
|
PHUB_DEVICE_EXTENSION HubDeviceExtension;
|
|
|
|
|
PWORK_ITEM_DATA WorkItemData;
|
|
|
|
|
PORT_STATUS_CHANGE PortStatus;
|
2015-02-14 19:07:36 +00:00
|
|
|
|
ULONG PortId;
|
2012-02-08 15:50:52 +00:00
|
|
|
|
BOOLEAN SignalResetComplete = FALSE;
|
2011-06-01 08:10:41 +00:00
|
|
|
|
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("Entered DeviceStatusChangeThread, Context %x\n", Context);
|
2011-06-01 08:10:41 +00:00
|
|
|
|
|
2011-05-04 12:58:42 +00:00
|
|
|
|
WorkItemData = (PWORK_ITEM_DATA)Context;
|
|
|
|
|
DeviceObject = (PDEVICE_OBJECT)WorkItemData->Context;
|
|
|
|
|
HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
2011-05-07 14:49:02 +00:00
|
|
|
|
RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
|
2011-05-04 12:58:42 +00:00
|
|
|
|
//
|
2011-05-04 21:45:55 +00:00
|
|
|
|
// Loop all ports
|
2011-05-04 12:58:42 +00:00
|
|
|
|
//
|
|
|
|
|
for (PortId = 1; PortId <= HubDeviceExtension->UsbExtHubInfo.NumberOfPorts; PortId++)
|
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
// Get Port Status
|
|
|
|
|
//
|
2011-05-07 14:49:02 +00:00
|
|
|
|
Status = GetPortStatusAndChange(RootHubDeviceObject, PortId, &PortStatus);
|
2011-05-04 12:58:42 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to get port status for port %d, Status %x\n", PortId, Status);
|
|
|
|
|
// FIXME: Do we really want to halt further SCE requests?
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-13 22:03:47 +00:00
|
|
|
|
DPRINT("Port %d Status %x\n", PortId, PortStatus.Status);
|
|
|
|
|
DPRINT("Port %d Change %x\n", PortId, PortStatus.Change);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
|
2011-05-07 14:49:02 +00:00
|
|
|
|
|
2011-05-04 12:58:42 +00:00
|
|
|
|
//
|
|
|
|
|
// Check for new device connection
|
|
|
|
|
//
|
2011-05-07 14:49:02 +00:00
|
|
|
|
if (PortStatus.Change & USB_PORT_STATUS_CONNECT)
|
2011-05-04 12:58:42 +00:00
|
|
|
|
{
|
|
|
|
|
//
|
2014-11-02 11:30:14 +00:00
|
|
|
|
// Clear Port Connect
|
2011-05-04 12:58:42 +00:00
|
|
|
|
//
|
2011-05-07 14:49:02 +00:00
|
|
|
|
Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_CONNECTION);
|
2011-05-04 12:58:42 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to clear connection change for port %d\n", PortId);
|
2012-02-25 04:45:30 +00:00
|
|
|
|
continue;
|
2011-05-04 12:58:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
2011-05-07 14:49:02 +00:00
|
|
|
|
// Is this a connect or disconnect?
|
2011-05-04 12:58:42 +00:00
|
|
|
|
//
|
2011-05-07 14:49:02 +00:00
|
|
|
|
if (!(PortStatus.Status & USB_PORT_STATUS_CONNECT))
|
2011-05-04 12:58:42 +00:00
|
|
|
|
{
|
2011-05-07 14:49:02 +00:00
|
|
|
|
DPRINT1("Device disconnected from port %d\n", PortId);
|
|
|
|
|
|
2012-01-22 21:58:06 +00:00
|
|
|
|
Status = DestroyUsbChildDeviceObject(DeviceObject, PortId);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to delete child device object after disconnect\n");
|
2012-02-25 04:45:30 +00:00
|
|
|
|
continue;
|
2012-01-22 21:58:06 +00:00
|
|
|
|
}
|
2011-05-04 12:58:42 +00:00
|
|
|
|
}
|
2011-05-07 14:49:02 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Device connected from port %d\n", PortId);
|
|
|
|
|
|
|
|
|
|
// No SCE completion done for clearing C_PORT_CONNECT
|
2011-05-08 12:24:26 +00:00
|
|
|
|
|
2011-05-07 14:49:02 +00:00
|
|
|
|
//
|
|
|
|
|
// Reset Port
|
|
|
|
|
//
|
|
|
|
|
Status = SetPortFeature(RootHubDeviceObject, PortId, PORT_RESET);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to reset port %d\n", PortId);
|
2012-02-25 05:46:19 +00:00
|
|
|
|
SignalResetComplete = TRUE;
|
2012-02-25 04:45:30 +00:00
|
|
|
|
continue;
|
2011-05-07 14:49:02 +00:00
|
|
|
|
}
|
2011-05-08 12:24:26 +00:00
|
|
|
|
}
|
2011-05-04 21:45:55 +00:00
|
|
|
|
}
|
2011-05-07 14:49:02 +00:00
|
|
|
|
else if (PortStatus.Change & USB_PORT_STATUS_ENABLE)
|
2011-05-04 21:45:55 +00:00
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
// Clear Enable
|
|
|
|
|
//
|
2011-05-07 14:49:02 +00:00
|
|
|
|
Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_ENABLE);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
2011-05-04 12:58:42 +00:00
|
|
|
|
{
|
2011-05-04 21:45:55 +00:00
|
|
|
|
DPRINT1("Failed to clear enable change on port %d\n", PortId);
|
2012-02-25 04:45:30 +00:00
|
|
|
|
continue;
|
2011-05-04 12:58:42 +00:00
|
|
|
|
}
|
2011-05-04 21:45:55 +00:00
|
|
|
|
}
|
2011-05-07 14:49:02 +00:00
|
|
|
|
else if (PortStatus.Change & USB_PORT_STATUS_RESET)
|
2011-05-04 21:45:55 +00:00
|
|
|
|
{
|
2012-02-25 05:46:19 +00:00
|
|
|
|
//
|
|
|
|
|
// Request event signalling later
|
|
|
|
|
//
|
|
|
|
|
SignalResetComplete = TRUE;
|
|
|
|
|
|
2011-05-04 21:45:55 +00:00
|
|
|
|
//
|
|
|
|
|
// Clear Reset
|
|
|
|
|
//
|
2011-05-07 14:49:02 +00:00
|
|
|
|
Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_RESET);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to clear reset change on port %d\n", PortId);
|
2012-02-25 04:45:30 +00:00
|
|
|
|
continue;
|
2011-05-04 21:45:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-07 14:49:02 +00:00
|
|
|
|
//
|
|
|
|
|
// Get Port Status
|
|
|
|
|
//
|
|
|
|
|
Status = GetPortStatusAndChange(RootHubDeviceObject, PortId, &PortStatus);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to get port status for port %d, Status %x\n", PortId, Status);
|
|
|
|
|
// FIXME: Do we really want to halt further SCE requests?
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-13 22:03:47 +00:00
|
|
|
|
DPRINT("Port %d Status %x\n", PortId, PortStatus.Status);
|
|
|
|
|
DPRINT("Port %d Change %x\n", PortId, PortStatus.Change);
|
2011-05-07 14:49:02 +00:00
|
|
|
|
|
2011-05-11 02:25:11 +00:00
|
|
|
|
//
|
|
|
|
|
// Check that reset was cleared
|
|
|
|
|
//
|
2011-05-07 14:49:02 +00:00
|
|
|
|
if(PortStatus.Change & USB_PORT_STATUS_RESET)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Port did not clear reset! Possible Hardware problem!\n");
|
2012-02-25 04:45:30 +00:00
|
|
|
|
continue;
|
2011-05-07 14:49:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-11 02:25:11 +00:00
|
|
|
|
//
|
|
|
|
|
// Check if the device is still connected
|
|
|
|
|
//
|
|
|
|
|
if (!(PortStatus.Status & USB_PORT_STATUS_CONNECT))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Device has been disconnected\n");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-07 14:49:02 +00:00
|
|
|
|
//
|
|
|
|
|
// Make sure its Connected and Enabled
|
|
|
|
|
//
|
|
|
|
|
if (!(PortStatus.Status & (USB_PORT_STATUS_CONNECT | USB_PORT_STATUS_ENABLE)))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Usb Device is not connected and enabled!\n");
|
|
|
|
|
//
|
|
|
|
|
// Attempt another reset
|
|
|
|
|
//
|
|
|
|
|
Status = SetPortFeature(RootHubDeviceObject, PortId, PORT_RESET);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to reset port %d\n", PortId);
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2011-05-04 12:58:42 +00:00
|
|
|
|
|
|
|
|
|
//
|
2012-01-26 00:02:03 +00:00
|
|
|
|
// This is a new device
|
2011-05-04 12:58:42 +00:00
|
|
|
|
//
|
2012-02-03 11:29:03 +00:00
|
|
|
|
Status = CreateUsbChildDeviceObject(DeviceObject, PortId, NULL, PortStatus.Status);
|
2011-05-04 12:58:42 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-08 15:50:52 +00:00
|
|
|
|
ExFreePool(WorkItemData);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
|
2011-05-04 12:58:42 +00:00
|
|
|
|
//
|
|
|
|
|
// Send another SCE Request
|
|
|
|
|
//
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("Sending another SCE!\n");
|
2011-05-04 12:58:42 +00:00
|
|
|
|
QueryStatusChangeEndpoint(DeviceObject);
|
2012-02-08 15:50:52 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Check if a reset event was satisfied
|
|
|
|
|
//
|
|
|
|
|
if (SignalResetComplete)
|
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
// Signal anyone waiting on it
|
|
|
|
|
//
|
|
|
|
|
KeSetEvent(&HubDeviceExtension->ResetComplete, IO_NO_INCREMENT, FALSE);
|
|
|
|
|
}
|
2011-05-04 12:58:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
2012-01-22 23:25:33 +00:00
|
|
|
|
NTAPI
|
2011-05-04 12:58:42 +00:00
|
|
|
|
StatusChangeEndpointCompletion(
|
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
|
IN PIRP Irp,
|
|
|
|
|
IN PVOID Context)
|
|
|
|
|
{
|
|
|
|
|
PDEVICE_OBJECT RealDeviceObject;
|
|
|
|
|
PHUB_DEVICE_EXTENSION HubDeviceExtension;
|
|
|
|
|
PWORK_ITEM_DATA WorkItemData;
|
|
|
|
|
|
|
|
|
|
RealDeviceObject = (PDEVICE_OBJECT)Context;
|
|
|
|
|
HubDeviceExtension = (PHUB_DEVICE_EXTENSION)RealDeviceObject->DeviceExtension;
|
|
|
|
|
|
|
|
|
|
//
|
2011-05-07 14:49:02 +00:00
|
|
|
|
// NOTE: USBPORT frees this IRP
|
2011-05-04 12:58:42 +00:00
|
|
|
|
//
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("Received Irp %x, HubDeviceExtension->PendingSCEIrp %x\n", Irp, HubDeviceExtension->PendingSCEIrp);
|
2011-05-07 14:49:02 +00:00
|
|
|
|
//IoFreeIrp(Irp);
|
2011-05-04 12:58:42 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Create and initialize work item data
|
|
|
|
|
//
|
|
|
|
|
WorkItemData = ExAllocatePoolWithTag(NonPagedPool, sizeof(WORK_ITEM_DATA), USB_HUB_TAG);
|
|
|
|
|
if (!WorkItemData)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to allocate memory!n");
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
}
|
|
|
|
|
WorkItemData->Context = RealDeviceObject;
|
2012-02-08 15:50:52 +00:00
|
|
|
|
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("Queuing work item\n");
|
2011-05-04 12:58:42 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Queue the work item to handle initializing the device
|
|
|
|
|
//
|
2012-02-08 15:50:52 +00:00
|
|
|
|
ExInitializeWorkItem(&WorkItemData->WorkItem, DeviceStatusChangeThread, (PVOID)WorkItemData);
|
2011-05-04 12:58:42 +00:00
|
|
|
|
ExQueueWorkItem(&WorkItemData->WorkItem, DelayedWorkQueue);
|
|
|
|
|
|
2011-05-04 21:45:55 +00:00
|
|
|
|
//
|
|
|
|
|
// Return more processing required so the IO Manger doesn’t try to mess with IRP just freed
|
|
|
|
|
//
|
2011-05-04 12:58:42 +00:00
|
|
|
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
|
QueryStatusChangeEndpoint(
|
|
|
|
|
IN PDEVICE_OBJECT DeviceObject)
|
|
|
|
|
{
|
2011-05-07 14:49:02 +00:00
|
|
|
|
PDEVICE_OBJECT RootHubDeviceObject;
|
2011-05-04 12:58:42 +00:00
|
|
|
|
PIO_STACK_LOCATION Stack;
|
|
|
|
|
PHUB_DEVICE_EXTENSION HubDeviceExtension;
|
2011-05-07 14:49:02 +00:00
|
|
|
|
PURB PendingSCEUrb;
|
2011-05-04 12:58:42 +00:00
|
|
|
|
|
|
|
|
|
HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
2011-05-07 14:49:02 +00:00
|
|
|
|
RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Allocate a URB
|
|
|
|
|
//
|
|
|
|
|
PendingSCEUrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
|
2011-05-04 12:58:42 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Initialize URB for Status Change Endpoint request
|
|
|
|
|
//
|
2011-05-07 14:49:02 +00:00
|
|
|
|
UsbBuildInterruptOrBulkTransferRequest(PendingSCEUrb,
|
2011-05-04 12:58:42 +00:00
|
|
|
|
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
|
|
|
|
|
HubDeviceExtension->PipeHandle,
|
|
|
|
|
HubDeviceExtension->PortStatusChange,
|
|
|
|
|
NULL,
|
|
|
|
|
sizeof(USHORT) * 2 * HubDeviceExtension->UsbExtHubInfo.NumberOfPorts,
|
|
|
|
|
USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
|
|
|
|
|
NULL);
|
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// Set the device handle
|
|
|
|
|
PendingSCEUrb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
|
2011-05-04 12:58:42 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Allocate an Irp
|
|
|
|
|
//
|
2011-05-07 14:49:02 +00:00
|
|
|
|
HubDeviceExtension->PendingSCEIrp = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
IoSizeOfIrp(RootHubDeviceObject->StackSize),
|
|
|
|
|
USB_HUB_TAG);
|
|
|
|
|
/*
|
|
|
|
|
HubDeviceExtension->PendingSCEIrp = IoAllocateIrp(RootHubDeviceObject->StackSize,
|
|
|
|
|
FALSE);
|
|
|
|
|
*/
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("Allocated IRP %x\n", HubDeviceExtension->PendingSCEIrp);
|
2011-05-04 12:58:42 +00:00
|
|
|
|
|
|
|
|
|
if (!HubDeviceExtension->PendingSCEIrp)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("USBHUB: Failed to allocate IRP for SCE request!\n");
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Initialize the IRP
|
|
|
|
|
//
|
2011-05-07 14:49:02 +00:00
|
|
|
|
IoInitializeIrp(HubDeviceExtension->PendingSCEIrp,
|
|
|
|
|
IoSizeOfIrp(RootHubDeviceObject->StackSize),
|
|
|
|
|
RootHubDeviceObject->StackSize);
|
|
|
|
|
|
2011-05-04 12:58:42 +00:00
|
|
|
|
HubDeviceExtension->PendingSCEIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
|
|
|
|
HubDeviceExtension->PendingSCEIrp->IoStatus.Information = 0;
|
|
|
|
|
HubDeviceExtension->PendingSCEIrp->Flags = 0;
|
|
|
|
|
HubDeviceExtension->PendingSCEIrp->UserBuffer = NULL;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Get the Next Stack Location and Initialize it
|
|
|
|
|
//
|
|
|
|
|
Stack = IoGetNextIrpStackLocation(HubDeviceExtension->PendingSCEIrp);
|
2011-05-07 14:49:02 +00:00
|
|
|
|
Stack->DeviceObject = DeviceObject;
|
|
|
|
|
Stack->Parameters.Others.Argument1 = PendingSCEUrb;
|
2011-05-04 12:58:42 +00:00
|
|
|
|
Stack->Parameters.Others.Argument2 = NULL;
|
|
|
|
|
Stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
|
|
|
|
|
Stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Set the completion routine for when device is connected to root hub
|
|
|
|
|
//
|
|
|
|
|
IoSetCompletionRoutine(HubDeviceExtension->PendingSCEIrp,
|
2012-01-22 23:56:03 +00:00
|
|
|
|
StatusChangeEndpointCompletion,
|
2011-05-04 12:58:42 +00:00
|
|
|
|
DeviceObject,
|
|
|
|
|
TRUE,
|
|
|
|
|
TRUE,
|
|
|
|
|
TRUE);
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Send to RootHub
|
|
|
|
|
//
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("DeviceObject is %x\n", DeviceObject);
|
|
|
|
|
DPRINT("Iocalldriver %x with irp %x\n", RootHubDeviceObject, HubDeviceExtension->PendingSCEIrp);
|
2013-07-20 00:10:31 +00:00
|
|
|
|
IoCallDriver(RootHubDeviceObject, HubDeviceExtension->PendingSCEIrp);
|
2011-05-04 12:58:42 +00:00
|
|
|
|
|
|
|
|
|
return STATUS_PENDING;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
|
QueryInterface(
|
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
|
IN CONST GUID InterfaceType,
|
|
|
|
|
IN LONG Size,
|
|
|
|
|
IN LONG Version,
|
|
|
|
|
OUT PVOID Interface)
|
|
|
|
|
{
|
|
|
|
|
KEVENT Event;
|
|
|
|
|
PIRP Irp;
|
|
|
|
|
IO_STATUS_BLOCK IoStatus;
|
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
PIO_STACK_LOCATION Stack = NULL;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Initialize the Event used to wait for Irp completion
|
|
|
|
|
//
|
|
|
|
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Build Control Request
|
|
|
|
|
//
|
|
|
|
|
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
|
|
|
|
|
DeviceObject,
|
|
|
|
|
NULL,
|
|
|
|
|
0,
|
|
|
|
|
NULL,
|
|
|
|
|
&Event,
|
|
|
|
|
&IoStatus);
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Get Next Stack Location and Initialize it.
|
|
|
|
|
//
|
|
|
|
|
Stack = IoGetNextIrpStackLocation(Irp);
|
|
|
|
|
Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
|
|
|
|
|
Stack->Parameters.QueryInterface.InterfaceType= &InterfaceType;//USB_BUS_INTERFACE_HUB_GUID;
|
|
|
|
|
Stack->Parameters.QueryInterface.Size = Size;
|
|
|
|
|
Stack->Parameters.QueryInterface.Version = Version;
|
|
|
|
|
Stack->Parameters.QueryInterface.Interface = Interface;
|
|
|
|
|
Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
|
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
//
|
|
|
|
|
// Initialize the status block before sending the IRP
|
|
|
|
|
//
|
|
|
|
|
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
|
|
|
|
|
2011-05-04 12:58:42 +00:00
|
|
|
|
Status = IoCallDriver(DeviceObject, Irp);
|
|
|
|
|
|
|
|
|
|
if (Status == STATUS_PENDING)
|
|
|
|
|
{
|
|
|
|
|
DPRINT("Operation pending\n");
|
|
|
|
|
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
|
|
|
|
|
Status = IoStatus.Status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-04 01:07:21 +00:00
|
|
|
|
NTSTATUS
|
|
|
|
|
GetUsbDeviceDescriptor(
|
2011-05-04 12:58:42 +00:00
|
|
|
|
IN PDEVICE_OBJECT ChildDeviceObject,
|
|
|
|
|
IN UCHAR DescriptorType,
|
|
|
|
|
IN UCHAR Index,
|
|
|
|
|
IN USHORT LangId,
|
|
|
|
|
OUT PVOID TransferBuffer,
|
|
|
|
|
IN ULONG TransferBufferLength)
|
2011-05-04 01:07:21 +00:00
|
|
|
|
{
|
|
|
|
|
NTSTATUS Status;
|
2011-05-07 14:49:02 +00:00
|
|
|
|
PDEVICE_OBJECT RootHubDeviceObject;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
PURB Urb;
|
|
|
|
|
PHUB_DEVICE_EXTENSION HubDeviceExtension;
|
|
|
|
|
PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Get the Hubs Device Extension
|
|
|
|
|
//
|
|
|
|
|
ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)ChildDeviceObject->DeviceExtension;
|
|
|
|
|
HubDeviceExtension = (PHUB_DEVICE_EXTENSION) ChildDeviceExtension->ParentDeviceObject->DeviceExtension;
|
2011-05-07 14:49:02 +00:00
|
|
|
|
RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Allocate a URB
|
|
|
|
|
//
|
|
|
|
|
Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
|
|
|
|
|
if (!Urb)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to allocate memory for URB!\n");
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Zero it
|
|
|
|
|
//
|
|
|
|
|
RtlZeroMemory(Urb, sizeof(URB));
|
|
|
|
|
|
|
|
|
|
//
|
2011-05-12 12:58:07 +00:00
|
|
|
|
// Initialize URB for getting device descriptor
|
2011-05-04 01:07:21 +00:00
|
|
|
|
//
|
|
|
|
|
UsbBuildGetDescriptorRequest(Urb,
|
|
|
|
|
sizeof(Urb->UrbControlDescriptorRequest),
|
|
|
|
|
DescriptorType,
|
|
|
|
|
Index,
|
|
|
|
|
LangId,
|
2011-05-07 14:49:02 +00:00
|
|
|
|
TransferBuffer,
|
2011-05-04 01:07:21 +00:00
|
|
|
|
NULL,
|
|
|
|
|
TransferBufferLength,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Set the device handle
|
|
|
|
|
//
|
2011-05-04 21:45:55 +00:00
|
|
|
|
Urb->UrbHeader.UsbdDeviceHandle = (PVOID)ChildDeviceExtension->UsbDeviceHandle;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Query the Root Hub
|
|
|
|
|
//
|
2011-05-07 14:49:02 +00:00
|
|
|
|
Status = SubmitRequestToRootHub(RootHubDeviceObject,
|
2011-05-04 01:07:21 +00:00
|
|
|
|
IOCTL_INTERNAL_USB_SUBMIT_URB,
|
|
|
|
|
Urb,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-04 21:45:55 +00:00
|
|
|
|
NTSTATUS
|
|
|
|
|
GetUsbStringDescriptor(
|
|
|
|
|
IN PDEVICE_OBJECT ChildDeviceObject,
|
|
|
|
|
IN UCHAR Index,
|
|
|
|
|
IN USHORT LangId,
|
2011-05-08 12:24:26 +00:00
|
|
|
|
OUT PVOID *TransferBuffer,
|
|
|
|
|
OUT USHORT *Size)
|
2011-05-04 21:45:55 +00:00
|
|
|
|
{
|
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
PUSB_STRING_DESCRIPTOR StringDesc = NULL;
|
|
|
|
|
ULONG SizeNeeded;
|
2012-01-27 12:29:18 +00:00
|
|
|
|
LPWSTR Buffer;
|
2011-05-04 21:45:55 +00:00
|
|
|
|
|
|
|
|
|
StringDesc = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
sizeof(USB_STRING_DESCRIPTOR),
|
|
|
|
|
USB_HUB_TAG);
|
|
|
|
|
if (!StringDesc)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to allocate buffer for string!\n");
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Get the index string descriptor length
|
2011-05-07 16:10:09 +00:00
|
|
|
|
// FIXME: Implement LangIds
|
2011-05-04 21:45:55 +00:00
|
|
|
|
//
|
|
|
|
|
Status = GetUsbDeviceDescriptor(ChildDeviceObject,
|
|
|
|
|
USB_STRING_DESCRIPTOR_TYPE,
|
|
|
|
|
Index,
|
2011-05-07 16:10:09 +00:00
|
|
|
|
0x0409,
|
2011-05-04 21:45:55 +00:00
|
|
|
|
StringDesc,
|
|
|
|
|
sizeof(USB_STRING_DESCRIPTOR));
|
2011-05-07 16:10:09 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
2011-05-07 14:49:02 +00:00
|
|
|
|
{
|
2011-05-07 16:10:09 +00:00
|
|
|
|
DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status);
|
|
|
|
|
ExFreePool(StringDesc);
|
|
|
|
|
return Status;
|
2011-05-07 14:49:02 +00:00
|
|
|
|
}
|
|
|
|
|
DPRINT1("StringDesc->bLength %d\n", StringDesc->bLength);
|
2011-05-08 12:24:26 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Did we get something more than the length of the first two fields of structure?
|
|
|
|
|
//
|
|
|
|
|
if (StringDesc->bLength == 2)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("USB Device Error!\n");
|
|
|
|
|
ExFreePool(StringDesc);
|
|
|
|
|
return STATUS_DEVICE_DATA_ERROR;
|
|
|
|
|
}
|
2011-05-07 14:49:02 +00:00
|
|
|
|
SizeNeeded = StringDesc->bLength + sizeof(WCHAR);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Free String
|
|
|
|
|
//
|
|
|
|
|
ExFreePool(StringDesc);
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Recreate with appropriate size
|
|
|
|
|
//
|
|
|
|
|
StringDesc = ExAllocatePoolWithTag(NonPagedPool,
|
2011-05-07 14:49:02 +00:00
|
|
|
|
SizeNeeded,
|
2011-05-04 21:45:55 +00:00
|
|
|
|
USB_HUB_TAG);
|
|
|
|
|
if (!StringDesc)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to allocate buffer for string!\n");
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
}
|
2011-05-07 16:10:09 +00:00
|
|
|
|
|
2011-05-07 14:49:02 +00:00
|
|
|
|
RtlZeroMemory(StringDesc, SizeNeeded);
|
2011-05-07 16:10:09 +00:00
|
|
|
|
|
2011-05-04 21:45:55 +00:00
|
|
|
|
//
|
|
|
|
|
// Get the string
|
|
|
|
|
//
|
|
|
|
|
Status = GetUsbDeviceDescriptor(ChildDeviceObject,
|
|
|
|
|
USB_STRING_DESCRIPTOR_TYPE,
|
|
|
|
|
Index,
|
2011-05-07 16:10:09 +00:00
|
|
|
|
0x0409,
|
2011-05-04 21:45:55 +00:00
|
|
|
|
StringDesc,
|
2011-05-07 14:49:02 +00:00
|
|
|
|
SizeNeeded);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
2011-05-07 16:10:09 +00:00
|
|
|
|
DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
ExFreePool(StringDesc);
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
2011-05-07 14:49:02 +00:00
|
|
|
|
// Allocate Buffer to return
|
2011-05-04 21:45:55 +00:00
|
|
|
|
//
|
2012-01-27 12:29:18 +00:00
|
|
|
|
Buffer = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
SizeNeeded,
|
|
|
|
|
USB_HUB_TAG);
|
|
|
|
|
if (!Buffer)
|
2011-05-04 21:45:55 +00:00
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to allocate buffer for string!\n");
|
|
|
|
|
ExFreePool(StringDesc);
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
RtlZeroMemory(Buffer, SizeNeeded);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Copy the string to destination
|
|
|
|
|
//
|
2012-01-27 12:29:18 +00:00
|
|
|
|
RtlCopyMemory(Buffer, StringDesc->bString, SizeNeeded - FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString));
|
2011-05-08 12:24:26 +00:00
|
|
|
|
*Size = SizeNeeded;
|
2012-01-27 12:29:18 +00:00
|
|
|
|
*TransferBuffer = Buffer;
|
2011-05-04 21:45:55 +00:00
|
|
|
|
|
|
|
|
|
ExFreePool(StringDesc);
|
|
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-23 23:29:54 +00:00
|
|
|
|
ULONG
|
|
|
|
|
IsCompositeDevice(
|
2012-01-23 23:41:40 +00:00
|
|
|
|
IN PUSB_DEVICE_DESCRIPTOR DeviceDescriptor,
|
|
|
|
|
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
|
2012-01-23 23:29:54 +00:00
|
|
|
|
{
|
2012-01-23 23:41:40 +00:00
|
|
|
|
if (DeviceDescriptor->bNumConfigurations != 1)
|
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
// composite device must have only one configuration
|
|
|
|
|
//
|
2012-01-29 23:11:21 +00:00
|
|
|
|
DPRINT1("IsCompositeDevice bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations);
|
2012-01-23 23:41:40 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ConfigurationDescriptor->bNumInterfaces < 2)
|
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
// composite device must have multiple interfaces
|
|
|
|
|
//
|
2012-01-29 23:11:21 +00:00
|
|
|
|
DPRINT1("IsCompositeDevice bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
|
2012-01-23 23:41:40 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-23 23:29:54 +00:00
|
|
|
|
if (DeviceDescriptor->bDeviceClass == 0)
|
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
// composite device
|
|
|
|
|
//
|
2012-01-24 17:00:30 +00:00
|
|
|
|
ASSERT(DeviceDescriptor->bDeviceSubClass == 0);
|
|
|
|
|
ASSERT(DeviceDescriptor->bDeviceProtocol == 0);
|
2012-01-29 23:11:21 +00:00
|
|
|
|
DPRINT1("IsCompositeDevice: TRUE\n");
|
2012-01-23 23:29:54 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-02 11:30:14 +00:00
|
|
|
|
if (DeviceDescriptor->bDeviceClass == 0xEF &&
|
2012-01-23 23:29:54 +00:00
|
|
|
|
DeviceDescriptor->bDeviceSubClass == 0x02 &&
|
|
|
|
|
DeviceDescriptor->bDeviceProtocol == 0x01)
|
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
// USB-IF association descriptor
|
|
|
|
|
//
|
2012-01-29 23:11:21 +00:00
|
|
|
|
DPRINT1("IsCompositeDevice: TRUE\n");
|
2012-01-23 23:29:54 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-29 23:11:21 +00:00
|
|
|
|
DPRINT1("DeviceDescriptor bDeviceClass %x bDeviceSubClass %x bDeviceProtocol %x\n", DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass, DeviceDescriptor->bDeviceProtocol);
|
|
|
|
|
|
2012-01-23 23:29:54 +00:00
|
|
|
|
//
|
|
|
|
|
// not a composite device
|
|
|
|
|
//
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-08 12:24:26 +00:00
|
|
|
|
NTSTATUS
|
|
|
|
|
CreateDeviceIds(
|
|
|
|
|
PDEVICE_OBJECT UsbChildDeviceObject)
|
|
|
|
|
{
|
2012-01-20 22:35:52 +00:00
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
2012-01-27 12:29:18 +00:00
|
|
|
|
ULONG Index = 0;
|
|
|
|
|
LPWSTR DeviceString;
|
|
|
|
|
WCHAR Buffer[200];
|
2011-05-08 12:24:26 +00:00
|
|
|
|
PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
|
2012-10-22 11:33:26 +00:00
|
|
|
|
PHUB_DEVICE_EXTENSION HubDeviceExtension;
|
2012-01-23 23:29:54 +00:00
|
|
|
|
PUSB_DEVICE_DESCRIPTOR DeviceDescriptor;
|
2012-01-24 17:00:30 +00:00
|
|
|
|
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
|
|
|
|
|
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
2011-05-08 12:24:26 +00:00
|
|
|
|
|
2012-01-23 23:29:54 +00:00
|
|
|
|
//
|
|
|
|
|
// get child device extension
|
|
|
|
|
//
|
2011-05-08 12:24:26 +00:00
|
|
|
|
UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)UsbChildDeviceObject->DeviceExtension;
|
|
|
|
|
|
2012-10-22 11:33:26 +00:00
|
|
|
|
// get hub device extension
|
|
|
|
|
HubDeviceExtension = (PHUB_DEVICE_EXTENSION) UsbChildExtension->ParentDeviceObject->DeviceExtension;
|
|
|
|
|
|
2012-01-23 23:29:54 +00:00
|
|
|
|
//
|
|
|
|
|
// get device descriptor
|
|
|
|
|
//
|
|
|
|
|
DeviceDescriptor = &UsbChildExtension->DeviceDesc;
|
|
|
|
|
|
2012-01-24 17:00:30 +00:00
|
|
|
|
//
|
|
|
|
|
// get configuration descriptor
|
|
|
|
|
//
|
|
|
|
|
ConfigurationDescriptor = UsbChildExtension->FullConfigDesc;
|
|
|
|
|
|
|
|
|
|
//
|
2012-01-27 12:29:18 +00:00
|
|
|
|
// use first interface descriptor available
|
2012-01-24 17:00:30 +00:00
|
|
|
|
//
|
2012-01-27 12:29:18 +00:00
|
|
|
|
InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, 0, -1, -1, -1, -1);
|
2014-02-09 13:59:25 +00:00
|
|
|
|
if (InterfaceDescriptor == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Error USBD_ParseConfigurationDescriptorEx failed to parse interface descriptor\n");
|
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-27 12:29:18 +00:00
|
|
|
|
ASSERT(InterfaceDescriptor);
|
2012-01-24 17:00:30 +00:00
|
|
|
|
|
2011-05-08 12:24:26 +00:00
|
|
|
|
//
|
|
|
|
|
// Construct the CompatibleIds
|
|
|
|
|
//
|
2012-01-24 17:00:30 +00:00
|
|
|
|
if (IsCompositeDevice(DeviceDescriptor, ConfigurationDescriptor))
|
2011-05-08 12:24:26 +00:00
|
|
|
|
{
|
2012-01-24 17:00:30 +00:00
|
|
|
|
//
|
|
|
|
|
// sanity checks
|
|
|
|
|
//
|
|
|
|
|
ASSERT(DeviceDescriptor->bNumConfigurations == 1);
|
|
|
|
|
ASSERT(ConfigurationDescriptor->bNumInterfaces > 1);
|
2012-01-27 12:29:18 +00:00
|
|
|
|
Index += swprintf(&Buffer[Index],
|
2012-01-23 23:29:54 +00:00
|
|
|
|
L"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x",
|
|
|
|
|
DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass, DeviceDescriptor->bDeviceProtocol) + 1;
|
2012-01-27 12:29:18 +00:00
|
|
|
|
Index += swprintf(&Buffer[Index],
|
2012-01-23 23:29:54 +00:00
|
|
|
|
L"USB\\DevClass_%02x&SubClass_%02x",
|
|
|
|
|
DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass) + 1;
|
2012-01-27 12:29:18 +00:00
|
|
|
|
Index += swprintf(&Buffer[Index],
|
2012-01-23 23:29:54 +00:00
|
|
|
|
L"USB\\DevClass_%02x",
|
|
|
|
|
DeviceDescriptor->bDeviceClass) + 1;
|
2012-01-27 12:29:18 +00:00
|
|
|
|
Index += swprintf(&Buffer[Index],
|
2012-01-23 23:29:54 +00:00
|
|
|
|
L"USB\\COMPOSITE") + 1;
|
2011-05-08 12:24:26 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2012-01-24 17:00:30 +00:00
|
|
|
|
//
|
|
|
|
|
// FIXME: support multiple configurations
|
|
|
|
|
//
|
|
|
|
|
ASSERT(DeviceDescriptor->bNumConfigurations == 1);
|
|
|
|
|
|
|
|
|
|
if (DeviceDescriptor->bDeviceClass == 0)
|
|
|
|
|
{
|
2014-11-02 11:30:14 +00:00
|
|
|
|
Index += swprintf(&Buffer[Index],
|
2012-01-24 17:00:30 +00:00
|
|
|
|
L"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
|
|
|
|
|
InterfaceDescriptor->bInterfaceClass, InterfaceDescriptor->bInterfaceSubClass, InterfaceDescriptor->bInterfaceProtocol) + 1;
|
2012-01-27 12:29:18 +00:00
|
|
|
|
Index += swprintf(&Buffer[Index],
|
2012-01-24 17:00:30 +00:00
|
|
|
|
L"USB\\Class_%02x&SubClass_%02x",
|
|
|
|
|
InterfaceDescriptor->bInterfaceClass, InterfaceDescriptor->bInterfaceSubClass) + 1;
|
2012-01-27 12:29:18 +00:00
|
|
|
|
Index += swprintf(&Buffer[Index],
|
2012-01-24 17:00:30 +00:00
|
|
|
|
L"USB\\Class_%02x",
|
|
|
|
|
InterfaceDescriptor->bInterfaceClass) + 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2014-11-02 11:30:14 +00:00
|
|
|
|
Index += swprintf(&Buffer[Index],
|
2011-05-08 12:24:26 +00:00
|
|
|
|
L"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
|
2012-01-23 23:29:54 +00:00
|
|
|
|
DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass, DeviceDescriptor->bDeviceProtocol) + 1;
|
2012-01-27 12:29:18 +00:00
|
|
|
|
Index += swprintf(&Buffer[Index],
|
2011-05-08 12:24:26 +00:00
|
|
|
|
L"USB\\Class_%02x&SubClass_%02x",
|
2012-01-23 23:29:54 +00:00
|
|
|
|
DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass) + 1;
|
2012-01-27 12:29:18 +00:00
|
|
|
|
Index += swprintf(&Buffer[Index],
|
2011-05-08 12:24:26 +00:00
|
|
|
|
L"USB\\Class_%02x",
|
2012-01-23 23:29:54 +00:00
|
|
|
|
DeviceDescriptor->bDeviceClass) + 1;
|
2012-01-24 17:00:30 +00:00
|
|
|
|
}
|
2011-05-08 12:24:26 +00:00
|
|
|
|
}
|
2012-01-23 23:29:54 +00:00
|
|
|
|
|
2011-05-08 12:24:26 +00:00
|
|
|
|
//
|
2012-01-27 12:29:18 +00:00
|
|
|
|
// now allocate the buffer
|
2011-05-08 12:24:26 +00:00
|
|
|
|
//
|
2012-01-27 12:29:18 +00:00
|
|
|
|
DeviceString = ExAllocatePool(NonPagedPool, (Index + 1) * sizeof(WCHAR));
|
|
|
|
|
if (!DeviceString)
|
2011-05-08 12:24:26 +00:00
|
|
|
|
{
|
2012-01-27 12:29:18 +00:00
|
|
|
|
//
|
|
|
|
|
// no memory
|
|
|
|
|
//
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
2011-05-08 12:24:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
2012-01-27 12:29:18 +00:00
|
|
|
|
// copy buffer
|
2011-05-08 12:24:26 +00:00
|
|
|
|
//
|
2012-01-27 12:29:18 +00:00
|
|
|
|
RtlCopyMemory(DeviceString, Buffer, Index * sizeof(WCHAR));
|
|
|
|
|
DeviceString[Index] = UNICODE_NULL;
|
|
|
|
|
UsbChildExtension->usCompatibleIds.Buffer = DeviceString;
|
|
|
|
|
UsbChildExtension->usCompatibleIds.Length = Index * sizeof(WCHAR);
|
|
|
|
|
UsbChildExtension->usCompatibleIds.MaximumLength = (Index + 1) * sizeof(WCHAR);
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("usCompatibleIds %wZ\n", &UsbChildExtension->usCompatibleIds);
|
2012-01-27 12:29:18 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Construct DeviceId string
|
|
|
|
|
//
|
|
|
|
|
Index = swprintf(Buffer, L"USB\\Vid_%04x&Pid_%04x", UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct) + 1;
|
2011-05-08 12:24:26 +00:00
|
|
|
|
|
|
|
|
|
//
|
2012-01-27 12:29:18 +00:00
|
|
|
|
// now allocate the buffer
|
2011-05-08 12:24:26 +00:00
|
|
|
|
//
|
2012-01-27 12:29:18 +00:00
|
|
|
|
DeviceString = ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR));
|
|
|
|
|
if (!DeviceString)
|
2011-05-08 12:24:26 +00:00
|
|
|
|
{
|
2012-01-27 12:29:18 +00:00
|
|
|
|
//
|
|
|
|
|
// no memory
|
|
|
|
|
//
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
2011-05-08 12:24:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-01-27 12:29:18 +00:00
|
|
|
|
//
|
|
|
|
|
// copy buffer
|
|
|
|
|
//
|
|
|
|
|
RtlCopyMemory(DeviceString, Buffer, Index * sizeof(WCHAR));
|
|
|
|
|
UsbChildExtension->usDeviceId.Buffer = DeviceString;
|
|
|
|
|
UsbChildExtension->usDeviceId.Length = (Index-1) * sizeof(WCHAR);
|
|
|
|
|
UsbChildExtension->usDeviceId.MaximumLength = Index * sizeof(WCHAR);
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("usDeviceId %wZ\n", &UsbChildExtension->usDeviceId);
|
2011-05-08 12:24:26 +00:00
|
|
|
|
|
|
|
|
|
//
|
2012-01-27 12:29:18 +00:00
|
|
|
|
// Construct HardwareIds
|
2011-05-08 12:24:26 +00:00
|
|
|
|
//
|
|
|
|
|
Index = 0;
|
2014-11-02 11:30:14 +00:00
|
|
|
|
Index += swprintf(&Buffer[Index],
|
2011-05-08 12:24:26 +00:00
|
|
|
|
L"USB\\Vid_%04x&Pid_%04x&Rev_%04x",
|
|
|
|
|
UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct, UsbChildExtension->DeviceDesc.bcdDevice) + 1;
|
2012-01-27 12:29:18 +00:00
|
|
|
|
Index += swprintf(&Buffer[Index],
|
2011-05-08 12:24:26 +00:00
|
|
|
|
L"USB\\Vid_%04x&Pid_%04x",
|
|
|
|
|
UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct) + 1;
|
2012-01-27 12:29:18 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// now allocate the buffer
|
|
|
|
|
//
|
|
|
|
|
DeviceString = ExAllocatePool(NonPagedPool, (Index + 1) * sizeof(WCHAR));
|
|
|
|
|
if (!DeviceString)
|
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
// no memory
|
|
|
|
|
//
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// copy buffer
|
|
|
|
|
//
|
|
|
|
|
RtlCopyMemory(DeviceString, Buffer, Index * sizeof(WCHAR));
|
|
|
|
|
DeviceString[Index] = UNICODE_NULL;
|
|
|
|
|
UsbChildExtension->usHardwareIds.Buffer = DeviceString;
|
|
|
|
|
UsbChildExtension->usHardwareIds.Length = (Index + 1) * sizeof(WCHAR);
|
|
|
|
|
UsbChildExtension->usHardwareIds.MaximumLength = (Index + 1) * sizeof(WCHAR);
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("usHardWareIds %wZ\n", &UsbChildExtension->usHardwareIds);
|
2011-05-08 12:24:26 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// FIXME: Handle Lang ids
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
//
|
2011-05-12 23:31:32 +00:00
|
|
|
|
// Get the product string if obe provided
|
2011-05-08 12:24:26 +00:00
|
|
|
|
//
|
2011-05-12 23:31:32 +00:00
|
|
|
|
if (UsbChildExtension->DeviceDesc.iProduct)
|
2011-05-08 12:24:26 +00:00
|
|
|
|
{
|
2011-05-12 23:31:32 +00:00
|
|
|
|
Status = GetUsbStringDescriptor(UsbChildDeviceObject,
|
|
|
|
|
UsbChildExtension->DeviceDesc.iProduct,
|
|
|
|
|
0,
|
|
|
|
|
(PVOID*)&UsbChildExtension->usTextDescription.Buffer,
|
|
|
|
|
&UsbChildExtension->usTextDescription.Length);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status);
|
2012-03-03 11:38:37 +00:00
|
|
|
|
RtlInitUnicodeString(&UsbChildExtension->usTextDescription, L"USB Device"); // FIXME NON-NLS
|
2012-02-09 15:33:09 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
UsbChildExtension->usTextDescription.MaximumLength = UsbChildExtension->usTextDescription.Length;
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("Usb TextDescription %wZ\n", &UsbChildExtension->usTextDescription);
|
2011-05-12 23:31:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2011-05-08 12:24:26 +00:00
|
|
|
|
|
|
|
|
|
//
|
2011-05-12 23:31:32 +00:00
|
|
|
|
// Get the Serial Number string if obe provided
|
2011-05-08 12:24:26 +00:00
|
|
|
|
//
|
2011-05-12 23:31:32 +00:00
|
|
|
|
if (UsbChildExtension->DeviceDesc.iSerialNumber)
|
2011-05-08 12:24:26 +00:00
|
|
|
|
{
|
2012-10-22 11:33:26 +00:00
|
|
|
|
LPWSTR SerialBuffer = NULL;
|
|
|
|
|
|
2011-05-12 23:31:32 +00:00
|
|
|
|
Status = GetUsbStringDescriptor(UsbChildDeviceObject,
|
|
|
|
|
UsbChildExtension->DeviceDesc.iSerialNumber,
|
|
|
|
|
0,
|
2012-10-22 11:33:26 +00:00
|
|
|
|
(PVOID*)&SerialBuffer,
|
2011-05-12 23:31:32 +00:00
|
|
|
|
&UsbChildExtension->usInstanceId.Length);
|
2012-12-04 19:20:12 +00:00
|
|
|
|
if (NT_SUCCESS(Status))
|
2011-05-12 23:31:32 +00:00
|
|
|
|
{
|
2012-12-04 19:20:12 +00:00
|
|
|
|
// construct instance id buffer
|
|
|
|
|
Index = swprintf(Buffer, L"%04d&%s", HubDeviceExtension->InstanceCount, SerialBuffer) + 1;
|
2016-05-09 17:44:16 +00:00
|
|
|
|
|
|
|
|
|
ExFreePool(SerialBuffer);
|
|
|
|
|
|
2012-12-04 19:20:12 +00:00
|
|
|
|
UsbChildExtension->usInstanceId.Buffer = (LPWSTR)ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR));
|
|
|
|
|
if (UsbChildExtension->usInstanceId.Buffer == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Error: failed to allocate %lu bytes\n", Index * sizeof(WCHAR));
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
}
|
2011-05-08 12:24:26 +00:00
|
|
|
|
|
2012-12-04 19:20:12 +00:00
|
|
|
|
//
|
|
|
|
|
// copy instance id
|
|
|
|
|
//
|
|
|
|
|
RtlCopyMemory(UsbChildExtension->usInstanceId.Buffer, Buffer, Index * sizeof(WCHAR));
|
|
|
|
|
UsbChildExtension->usInstanceId.Length = UsbChildExtension->usInstanceId.MaximumLength = Index * sizeof(WCHAR);
|
|
|
|
|
|
|
|
|
|
DPRINT("Usb InstanceId %wZ InstanceCount %x\n", &UsbChildExtension->usInstanceId, HubDeviceExtension->InstanceCount);
|
2012-10-22 11:33:26 +00:00
|
|
|
|
return Status;
|
|
|
|
|
}
|
2011-05-12 23:31:32 +00:00
|
|
|
|
}
|
2012-12-04 19:20:12 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// the device did not provide a serial number, or failed to retrieve the serial number
|
|
|
|
|
// lets create a pseudo instance id
|
|
|
|
|
//
|
|
|
|
|
Index = swprintf(Buffer, L"%04d&%04d", HubDeviceExtension->InstanceCount, UsbChildExtension->PortNumber) + 1;
|
|
|
|
|
UsbChildExtension->usInstanceId.Buffer = (LPWSTR)ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR));
|
|
|
|
|
if (UsbChildExtension->usInstanceId.Buffer == NULL)
|
2012-01-05 00:13:50 +00:00
|
|
|
|
{
|
2012-12-04 19:20:12 +00:00
|
|
|
|
DPRINT1("Error: failed to allocate %lu bytes\n", Index * sizeof(WCHAR));
|
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
return Status;
|
2012-01-05 00:13:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-12-04 19:20:12 +00:00
|
|
|
|
//
|
|
|
|
|
// copy instance id
|
|
|
|
|
//
|
|
|
|
|
RtlCopyMemory(UsbChildExtension->usInstanceId.Buffer, Buffer, Index * sizeof(WCHAR));
|
|
|
|
|
UsbChildExtension->usInstanceId.Length = UsbChildExtension->usInstanceId.MaximumLength = Index * sizeof(WCHAR);
|
|
|
|
|
|
|
|
|
|
DPRINT("usDeviceId %wZ\n", &UsbChildExtension->usInstanceId);
|
2012-03-03 11:38:37 +00:00
|
|
|
|
return STATUS_SUCCESS;
|
2011-05-08 12:24:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-01-22 21:58:06 +00:00
|
|
|
|
NTSTATUS
|
|
|
|
|
DestroyUsbChildDeviceObject(
|
|
|
|
|
IN PDEVICE_OBJECT UsbHubDeviceObject,
|
|
|
|
|
IN LONG PortId)
|
|
|
|
|
{
|
|
|
|
|
PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbHubDeviceObject->DeviceExtension;
|
|
|
|
|
PHUB_CHILDDEVICE_EXTENSION UsbChildExtension = NULL;
|
|
|
|
|
PDEVICE_OBJECT ChildDeviceObject = NULL;
|
|
|
|
|
ULONG Index = 0;
|
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
2012-01-22 21:58:06 +00:00
|
|
|
|
for (Index = 0; Index < USB_MAXCHILDREN; Index++)
|
|
|
|
|
{
|
|
|
|
|
if (HubDeviceExtension->ChildDeviceObject[Index])
|
|
|
|
|
{
|
|
|
|
|
UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)HubDeviceExtension->ChildDeviceObject[Index]->DeviceExtension;
|
|
|
|
|
|
|
|
|
|
/* Check if it matches the port ID */
|
|
|
|
|
if (UsbChildExtension->PortNumber == PortId)
|
|
|
|
|
{
|
|
|
|
|
/* We found it */
|
|
|
|
|
ChildDeviceObject = HubDeviceExtension->ChildDeviceObject[Index];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Fail the request if the device doesn't exist */
|
|
|
|
|
if (!ChildDeviceObject)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Removal request for non-existant device!\n");
|
2017-01-27 11:09:36 +00:00
|
|
|
|
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
2012-01-22 21:58:06 +00:00
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
DPRINT("Removing device on port %d (Child index: %d)\n", PortId, Index);
|
|
|
|
|
|
2012-01-22 21:58:06 +00:00
|
|
|
|
/* Remove the device from the table */
|
|
|
|
|
HubDeviceExtension->ChildDeviceObject[Index] = NULL;
|
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
|
|
|
|
|
2012-01-22 21:58:06 +00:00
|
|
|
|
/* Invalidate device relations for the root hub */
|
|
|
|
|
IoInvalidateDeviceRelations(HubDeviceExtension->RootHubPhysicalDeviceObject, BusRelations);
|
|
|
|
|
|
|
|
|
|
/* The rest of the removal process takes place in IRP_MN_REMOVE_DEVICE handling for the PDO */
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-04 01:07:21 +00:00
|
|
|
|
NTSTATUS
|
|
|
|
|
CreateUsbChildDeviceObject(
|
|
|
|
|
IN PDEVICE_OBJECT UsbHubDeviceObject,
|
|
|
|
|
IN LONG PortId,
|
2012-02-03 11:29:03 +00:00
|
|
|
|
OUT PDEVICE_OBJECT *UsbChildDeviceObject,
|
|
|
|
|
IN ULONG PortStatus)
|
2011-05-04 01:07:21 +00:00
|
|
|
|
{
|
2011-05-04 21:45:55 +00:00
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
PDEVICE_OBJECT RootHubDeviceObject, NewChildDeviceObject;
|
|
|
|
|
PHUB_DEVICE_EXTENSION HubDeviceExtension;
|
|
|
|
|
PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
|
|
|
|
|
PUSB_BUS_INTERFACE_HUB_V5 HubInterface;
|
2011-05-07 14:49:02 +00:00
|
|
|
|
ULONG ChildDeviceCount, UsbDeviceNumber = 0;
|
2011-05-04 21:45:55 +00:00
|
|
|
|
WCHAR CharDeviceName[64];
|
|
|
|
|
UNICODE_STRING DeviceName;
|
2012-10-24 15:40:46 +00:00
|
|
|
|
ULONG ConfigDescSize, DeviceDescSize, DeviceInfoSize;
|
2011-05-07 14:49:02 +00:00
|
|
|
|
PVOID HubInterfaceBusContext;
|
2011-05-08 12:24:26 +00:00
|
|
|
|
USB_CONFIGURATION_DESCRIPTOR ConfigDesc;
|
2011-05-04 21:45:55 +00:00
|
|
|
|
|
|
|
|
|
HubDeviceExtension = (PHUB_DEVICE_EXTENSION) UsbHubDeviceObject->DeviceExtension;
|
|
|
|
|
HubInterface = &HubDeviceExtension->HubInterface;
|
|
|
|
|
RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
|
2011-05-07 14:49:02 +00:00
|
|
|
|
HubInterfaceBusContext = HubDeviceExtension->UsbDInterface.BusContext;
|
2011-05-04 21:45:55 +00:00
|
|
|
|
|
|
|
|
|
while (TRUE)
|
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
// Create a Device Name
|
|
|
|
|
//
|
|
|
|
|
swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber);
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Initialize UnicodeString
|
|
|
|
|
//
|
|
|
|
|
RtlInitUnicodeString(&DeviceName, CharDeviceName);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2011-05-04 21:45:55 +00:00
|
|
|
|
//
|
|
|
|
|
// Create a DeviceObject
|
|
|
|
|
//
|
|
|
|
|
Status = IoCreateDevice(UsbHubDeviceObject->DriverObject,
|
|
|
|
|
sizeof(HUB_CHILDDEVICE_EXTENSION),
|
|
|
|
|
NULL,
|
|
|
|
|
FILE_DEVICE_CONTROLLER,
|
|
|
|
|
FILE_AUTOGENERATED_DEVICE_NAME,
|
|
|
|
|
FALSE,
|
|
|
|
|
&NewChildDeviceObject);
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Check if the name is already in use
|
|
|
|
|
//
|
|
|
|
|
if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
|
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
// Try next name
|
|
|
|
|
//
|
|
|
|
|
UsbDeviceNumber++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Check for other errors
|
|
|
|
|
//
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
2011-05-07 14:49:02 +00:00
|
|
|
|
DPRINT1("USBHUB: IoCreateDevice failed with status %x\n", Status);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("USBHUB: Created Device %x\n", NewChildDeviceObject);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NewChildDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Assign the device extensions
|
|
|
|
|
//
|
|
|
|
|
UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)NewChildDeviceObject->DeviceExtension;
|
|
|
|
|
RtlZeroMemory(UsbChildExtension, sizeof(HUB_CHILDDEVICE_EXTENSION));
|
|
|
|
|
UsbChildExtension->ParentDeviceObject = UsbHubDeviceObject;
|
2011-05-11 02:25:11 +00:00
|
|
|
|
UsbChildExtension->PortNumber = PortId;
|
2011-05-04 21:45:55 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Create the UsbDeviceObject
|
|
|
|
|
//
|
2011-05-07 14:49:02 +00:00
|
|
|
|
Status = HubInterface->CreateUsbDevice(HubInterfaceBusContext,
|
2011-05-04 21:45:55 +00:00
|
|
|
|
(PVOID)&UsbChildExtension->UsbDeviceHandle,
|
|
|
|
|
HubDeviceExtension->RootHubHandle,
|
2012-02-03 11:29:03 +00:00
|
|
|
|
PortStatus,
|
2011-05-04 21:45:55 +00:00
|
|
|
|
PortId);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
2011-05-07 14:49:02 +00:00
|
|
|
|
DPRINT1("USBHUB: CreateUsbDevice failed with status %x\n", Status);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
goto Cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Initialize UsbDevice
|
|
|
|
|
//
|
2011-05-07 14:49:02 +00:00
|
|
|
|
Status = HubInterface->InitializeUsbDevice(HubInterfaceBusContext, UsbChildExtension->UsbDeviceHandle);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
2011-05-07 14:49:02 +00:00
|
|
|
|
DPRINT1("USBHUB: InitializeUsbDevice failed with status %x\n", Status);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
goto Cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("Usb Device Handle %x\n", UsbChildExtension->UsbDeviceHandle);
|
2011-05-07 14:49:02 +00:00
|
|
|
|
|
2011-05-04 21:45:55 +00:00
|
|
|
|
ConfigDescSize = sizeof(USB_CONFIGURATION_DESCRIPTOR);
|
2011-05-07 14:49:02 +00:00
|
|
|
|
DeviceDescSize = sizeof(USB_DEVICE_DESCRIPTOR);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Get the descriptors
|
|
|
|
|
//
|
2011-05-07 14:49:02 +00:00
|
|
|
|
Status = HubInterface->GetUsbDescriptors(HubInterfaceBusContext,
|
2011-05-04 21:45:55 +00:00
|
|
|
|
UsbChildExtension->UsbDeviceHandle,
|
2011-05-07 14:49:02 +00:00
|
|
|
|
(PUCHAR)&UsbChildExtension->DeviceDesc,
|
2011-05-04 21:45:55 +00:00
|
|
|
|
&DeviceDescSize,
|
2011-05-08 12:24:26 +00:00
|
|
|
|
(PUCHAR)&ConfigDesc,
|
2011-05-04 21:45:55 +00:00
|
|
|
|
&ConfigDescSize);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
2011-05-07 14:49:02 +00:00
|
|
|
|
DPRINT1("USBHUB: GetUsbDescriptors failed with status %x\n", Status);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
goto Cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-13 22:03:47 +00:00
|
|
|
|
//DumpDeviceDescriptor(&UsbChildExtension->DeviceDesc);
|
|
|
|
|
//DumpConfigurationDescriptor(&ConfigDesc);
|
2011-05-07 14:49:02 +00:00
|
|
|
|
|
2011-05-04 21:45:55 +00:00
|
|
|
|
//
|
2011-05-08 12:24:26 +00:00
|
|
|
|
// FIXME: Support more than one configuration and one interface?
|
2011-05-04 21:45:55 +00:00
|
|
|
|
//
|
2011-05-08 12:24:26 +00:00
|
|
|
|
if (UsbChildExtension->DeviceDesc.bNumConfigurations > 1)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Warning: Device has more than one configuration. Only one configuration (the first) is supported!\n");
|
|
|
|
|
}
|
2011-05-04 21:45:55 +00:00
|
|
|
|
|
2011-05-08 12:24:26 +00:00
|
|
|
|
if (ConfigDesc.bNumInterfaces > 1)
|
|
|
|
|
{
|
2014-09-02 18:40:08 +00:00
|
|
|
|
DPRINT1("Warning: Device has more than one interface. Only one interface (the first) is currently supported\n");
|
2011-05-08 12:24:26 +00:00
|
|
|
|
}
|
2011-05-04 21:45:55 +00:00
|
|
|
|
|
2011-05-08 12:24:26 +00:00
|
|
|
|
ConfigDescSize = ConfigDesc.wTotalLength;
|
2011-05-04 21:45:55 +00:00
|
|
|
|
|
|
|
|
|
//
|
2011-05-08 12:24:26 +00:00
|
|
|
|
// Allocate memory for the first full descriptor, including interfaces and endpoints.
|
2011-05-04 21:45:55 +00:00
|
|
|
|
//
|
2011-05-08 12:24:26 +00:00
|
|
|
|
UsbChildExtension->FullConfigDesc = ExAllocatePoolWithTag(PagedPool, ConfigDescSize, USB_HUB_TAG);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
|
|
|
|
|
//
|
2011-05-08 12:24:26 +00:00
|
|
|
|
// Retrieve the full configuration descriptor
|
2011-05-04 21:45:55 +00:00
|
|
|
|
//
|
2011-05-08 12:24:26 +00:00
|
|
|
|
Status = GetUsbDeviceDescriptor(NewChildDeviceObject,
|
|
|
|
|
USB_CONFIGURATION_DESCRIPTOR_TYPE,
|
2011-05-04 21:45:55 +00:00
|
|
|
|
0,
|
2011-05-08 12:24:26 +00:00
|
|
|
|
0,
|
|
|
|
|
UsbChildExtension->FullConfigDesc,
|
|
|
|
|
ConfigDescSize);
|
|
|
|
|
|
2011-05-04 21:45:55 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
2011-05-08 12:24:26 +00:00
|
|
|
|
DPRINT1("USBHUB: GetUsbDeviceDescriptor failed with status %x\n", Status);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
goto Cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-24 15:40:46 +00:00
|
|
|
|
// query device details
|
2014-11-02 11:30:14 +00:00
|
|
|
|
Status = HubInterface->QueryDeviceInformation(HubInterfaceBusContext,
|
2012-10-24 15:40:46 +00:00
|
|
|
|
UsbChildExtension->UsbDeviceHandle,
|
|
|
|
|
&UsbChildExtension->DeviceInformation,
|
|
|
|
|
sizeof(USB_DEVICE_INFORMATION_0),
|
|
|
|
|
&DeviceInfoSize);
|
|
|
|
|
|
|
|
|
|
|
2012-01-29 23:11:21 +00:00
|
|
|
|
//DumpFullConfigurationDescriptor(UsbChildExtension->FullConfigDesc);
|
2011-05-07 14:49:02 +00:00
|
|
|
|
|
2011-05-08 12:24:26 +00:00
|
|
|
|
//
|
2014-09-02 18:40:08 +00:00
|
|
|
|
// Construct all the strings that will describe the device to PNP
|
2011-05-08 12:24:26 +00:00
|
|
|
|
//
|
|
|
|
|
Status = CreateDeviceIds(NewChildDeviceObject);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
2011-05-08 12:24:26 +00:00
|
|
|
|
DPRINT1("Failed to create strings needed to describe device to PNP.\n");
|
2011-05-04 21:45:55 +00:00
|
|
|
|
goto Cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
// copy device interface
|
|
|
|
|
RtlCopyMemory(&UsbChildExtension->DeviceInterface, &HubDeviceExtension->UsbDInterface, sizeof(USB_BUS_INTERFACE_USBDI_V2));
|
|
|
|
|
UsbChildExtension->DeviceInterface.InterfaceReference(UsbChildExtension->DeviceInterface.BusContext);
|
|
|
|
|
|
|
|
|
|
INITIALIZE_PNP_STATE(UsbChildExtension->Common);
|
|
|
|
|
|
|
|
|
|
IoInitializeRemoveLock(&UsbChildExtension->Common.RemoveLock, 'pbuH', 0, 0);
|
|
|
|
|
|
|
|
|
|
KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Find an empty slot in the child device array
|
|
|
|
|
//
|
|
|
|
|
for (ChildDeviceCount = 0; ChildDeviceCount < USB_MAXCHILDREN; ChildDeviceCount++)
|
|
|
|
|
{
|
|
|
|
|
if (HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] == NULL)
|
|
|
|
|
{
|
|
|
|
|
DPRINT("Found unused entry at %d\n", ChildDeviceCount);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Check if the limit has been reached for maximum usb devices
|
|
|
|
|
//
|
|
|
|
|
if (ChildDeviceCount == USB_MAXCHILDREN)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("USBHUB: Too many child devices!\n");
|
|
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
|
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
|
|
|
|
UsbChildExtension->DeviceInterface.InterfaceDereference(UsbChildExtension->DeviceInterface.BusContext);
|
|
|
|
|
goto Cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-04 21:45:55 +00:00
|
|
|
|
HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] = NewChildDeviceObject;
|
2012-10-22 11:33:26 +00:00
|
|
|
|
HubDeviceExtension->InstanceCount++;
|
2017-01-27 11:09:36 +00:00
|
|
|
|
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
|
|
|
|
|
IoInvalidateDeviceRelations(RootHubDeviceObject, BusRelations);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
return STATUS_SUCCESS;
|
2011-05-04 21:45:55 +00:00
|
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
|
|
2011-05-08 12:24:26 +00:00
|
|
|
|
//
|
|
|
|
|
// Remove the usb device if it was created
|
|
|
|
|
//
|
|
|
|
|
if (UsbChildExtension->UsbDeviceHandle)
|
|
|
|
|
HubInterface->RemoveUsbDevice(HubInterfaceBusContext, UsbChildExtension->UsbDeviceHandle, 0);
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Free full configuration descriptor if one was allocated
|
|
|
|
|
//
|
|
|
|
|
if (UsbChildExtension->FullConfigDesc)
|
|
|
|
|
ExFreePool(UsbChildExtension->FullConfigDesc);
|
|
|
|
|
|
2016-08-27 11:29:42 +00:00
|
|
|
|
//
|
|
|
|
|
// Free ID buffers if they were allocated in CreateDeviceIds()
|
|
|
|
|
//
|
|
|
|
|
if (UsbChildExtension->usCompatibleIds.Buffer)
|
|
|
|
|
ExFreePool(UsbChildExtension->usCompatibleIds.Buffer);
|
|
|
|
|
|
|
|
|
|
if (UsbChildExtension->usDeviceId.Buffer)
|
|
|
|
|
ExFreePool(UsbChildExtension->usDeviceId.Buffer);
|
|
|
|
|
|
|
|
|
|
if (UsbChildExtension->usHardwareIds.Buffer)
|
|
|
|
|
ExFreePool(UsbChildExtension->usHardwareIds.Buffer);
|
|
|
|
|
|
|
|
|
|
if (UsbChildExtension->usInstanceId.Buffer)
|
|
|
|
|
ExFreePool(UsbChildExtension->usInstanceId.Buffer);
|
|
|
|
|
|
2011-05-08 12:24:26 +00:00
|
|
|
|
//
|
|
|
|
|
// Delete the device object
|
|
|
|
|
//
|
2011-05-04 21:45:55 +00:00
|
|
|
|
IoDeleteDevice(NewChildDeviceObject);
|
|
|
|
|
return Status;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
|
USBHUB_FdoQueryBusRelations(
|
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
2017-01-27 11:09:36 +00:00
|
|
|
|
IN PDEVICE_RELATIONS RelationsFromTop,
|
2011-05-04 01:07:21 +00:00
|
|
|
|
OUT PDEVICE_RELATIONS* pDeviceRelations)
|
|
|
|
|
{
|
|
|
|
|
PHUB_DEVICE_EXTENSION HubDeviceExtension;
|
|
|
|
|
PDEVICE_RELATIONS DeviceRelations;
|
|
|
|
|
ULONG i;
|
2017-01-27 11:09:36 +00:00
|
|
|
|
ULONG ChildrenFromTop = 0;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
ULONG Children = 0;
|
|
|
|
|
ULONG NeededSize;
|
|
|
|
|
|
|
|
|
|
HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
|
|
|
|
|
2011-05-04 01:07:21 +00:00
|
|
|
|
//
|
|
|
|
|
// Count the number of children
|
|
|
|
|
//
|
|
|
|
|
for (i = 0; i < USB_MAXCHILDREN; i++)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (HubDeviceExtension->ChildDeviceObject[i] == NULL)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
Children++;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
if (RelationsFromTop)
|
|
|
|
|
{
|
|
|
|
|
ChildrenFromTop = RelationsFromTop->Count;
|
|
|
|
|
if (!Children)
|
|
|
|
|
{
|
|
|
|
|
// We have nothing to add
|
|
|
|
|
*pDeviceRelations = RelationsFromTop;
|
|
|
|
|
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NeededSize = sizeof(DEVICE_RELATIONS) + (Children + ChildrenFromTop - 1) * sizeof(PDEVICE_OBJECT);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Allocate DeviceRelations
|
|
|
|
|
//
|
|
|
|
|
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool,
|
|
|
|
|
NeededSize);
|
|
|
|
|
|
|
|
|
|
if (!DeviceRelations)
|
2017-01-27 11:09:36 +00:00
|
|
|
|
{
|
|
|
|
|
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
|
|
|
|
if (!RelationsFromTop)
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
else
|
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
|
|
|
}
|
|
|
|
|
// Copy the objects coming from top
|
|
|
|
|
if (ChildrenFromTop)
|
|
|
|
|
{
|
|
|
|
|
RtlCopyMemory(DeviceRelations->Objects, RelationsFromTop->Objects,
|
|
|
|
|
ChildrenFromTop * sizeof(PDEVICE_OBJECT));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DeviceRelations->Count = Children + ChildrenFromTop;
|
|
|
|
|
Children = ChildrenFromTop;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Fill in return structure
|
|
|
|
|
//
|
|
|
|
|
for (i = 0; i < USB_MAXCHILDREN; i++)
|
|
|
|
|
{
|
|
|
|
|
if (HubDeviceExtension->ChildDeviceObject[i])
|
|
|
|
|
{
|
2017-01-27 11:09:36 +00:00
|
|
|
|
// The PnP Manager removes the reference when appropriate.
|
2011-05-04 01:07:21 +00:00
|
|
|
|
ObReferenceObject(HubDeviceExtension->ChildDeviceObject[i]);
|
2011-05-04 21:45:55 +00:00
|
|
|
|
HubDeviceExtension->ChildDeviceObject[i]->Flags &= ~DO_DEVICE_INITIALIZING;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
DeviceRelations->Objects[Children++] = HubDeviceExtension->ChildDeviceObject[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
|
|
|
|
|
|
|
|
|
// We should do this, because replaced this with our's one
|
|
|
|
|
if (RelationsFromTop)
|
|
|
|
|
ExFreePool(RelationsFromTop);
|
|
|
|
|
|
2011-05-04 01:07:21 +00:00
|
|
|
|
ASSERT(Children == DeviceRelations->Count);
|
|
|
|
|
*pDeviceRelations = DeviceRelations;
|
|
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-07 14:49:02 +00:00
|
|
|
|
VOID
|
2012-01-23 00:27:30 +00:00
|
|
|
|
NTAPI
|
2011-05-07 14:49:02 +00:00
|
|
|
|
RootHubInitCallbackFunction(
|
|
|
|
|
PVOID Context)
|
|
|
|
|
{
|
|
|
|
|
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context;
|
2012-01-25 03:39:57 +00:00
|
|
|
|
NTSTATUS Status;
|
2012-01-26 00:11:15 +00:00
|
|
|
|
ULONG PortId;
|
|
|
|
|
PHUB_DEVICE_EXTENSION HubDeviceExtension;
|
|
|
|
|
PORT_STATUS_CHANGE StatusChange;
|
2012-01-25 03:39:57 +00:00
|
|
|
|
|
|
|
|
|
HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
2011-05-07 14:49:02 +00:00
|
|
|
|
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("RootHubInitCallbackFunction Sending the initial SCE Request %x\n", DeviceObject);
|
2012-01-25 03:39:57 +00:00
|
|
|
|
|
2012-01-30 22:19:47 +00:00
|
|
|
|
//
|
|
|
|
|
// Send the first SCE Request
|
|
|
|
|
//
|
|
|
|
|
QueryStatusChangeEndpoint(DeviceObject);
|
|
|
|
|
|
2012-01-25 03:39:57 +00:00
|
|
|
|
for (PortId = 1; PortId <= HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++)
|
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
// get port status
|
|
|
|
|
//
|
|
|
|
|
Status = GetPortStatusAndChange(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, &StatusChange);
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
// is there a device connected
|
|
|
|
|
//
|
|
|
|
|
if (StatusChange.Status & USB_PORT_STATUS_CONNECT)
|
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
// reset port
|
|
|
|
|
//
|
|
|
|
|
Status = SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_RESET);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
2012-02-08 15:50:52 +00:00
|
|
|
|
{
|
2012-01-25 03:39:57 +00:00
|
|
|
|
DPRINT1("Failed to reset on port %d\n", PortId);
|
2012-02-08 15:50:52 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
// wait for the reset to be handled since we want to enumerate synchronously
|
|
|
|
|
//
|
|
|
|
|
KeWaitForSingleObject(&HubDeviceExtension->ResetComplete,
|
|
|
|
|
Executive,
|
|
|
|
|
KernelMode,
|
|
|
|
|
FALSE,
|
|
|
|
|
NULL);
|
|
|
|
|
KeClearEvent(&HubDeviceExtension->ResetComplete);
|
|
|
|
|
}
|
2012-01-25 03:39:57 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-05-07 14:49:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-02-29 18:51:07 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-05-04 01:07:21 +00:00
|
|
|
|
NTSTATUS
|
2012-02-29 17:08:32 +00:00
|
|
|
|
USBHUB_FdoStartDevice(
|
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
|
IN PIRP Irp)
|
2011-05-04 01:07:21 +00:00
|
|
|
|
{
|
2012-02-29 17:08:32 +00:00
|
|
|
|
PURB Urb;
|
|
|
|
|
PUSB_INTERFACE_DESCRIPTOR Pid;
|
|
|
|
|
ULONG Result = 0, PortId;
|
|
|
|
|
USBD_INTERFACE_LIST_ENTRY InterfaceList[2] = {{NULL, NULL}, {NULL, NULL}};
|
|
|
|
|
PURB ConfigUrb = NULL;
|
|
|
|
|
ULONG HubStatus;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
|
PHUB_DEVICE_EXTENSION HubDeviceExtension;
|
2011-05-07 14:49:02 +00:00
|
|
|
|
PDEVICE_OBJECT RootHubDeviceObject;
|
2013-07-20 00:10:31 +00:00
|
|
|
|
PVOID HubInterfaceBusContext;
|
2012-01-26 00:11:15 +00:00
|
|
|
|
PORT_STATUS_CHANGE StatusChange;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// get hub device extension
|
2011-05-04 01:07:21 +00:00
|
|
|
|
HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// Allocated size including the sizeof USBD_INTERFACE_LIST_ENTRY
|
|
|
|
|
Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY), USB_HUB_TAG);
|
|
|
|
|
if (!Urb)
|
2011-05-04 01:07:21 +00:00
|
|
|
|
{
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// no memory
|
2017-01-27 11:09:36 +00:00
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto cleanup;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// zero urb
|
|
|
|
|
RtlZeroMemory(Urb, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY));
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// Get the Root Hub Pdo
|
|
|
|
|
Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject,
|
|
|
|
|
IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO,
|
|
|
|
|
&HubDeviceExtension->RootHubPhysicalDeviceObject,
|
|
|
|
|
&HubDeviceExtension->RootHubFunctionalDeviceObject);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
// failed to obtain hub pdo
|
|
|
|
|
DPRINT1("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO failed with %x\n", Status);
|
2017-01-27 11:09:36 +00:00
|
|
|
|
goto cleanup;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// sanity checks
|
|
|
|
|
ASSERT(HubDeviceExtension->RootHubPhysicalDeviceObject);
|
|
|
|
|
ASSERT(HubDeviceExtension->RootHubFunctionalDeviceObject);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// get roothub
|
|
|
|
|
RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// Send the StartDevice to RootHub
|
2017-01-27 11:09:36 +00:00
|
|
|
|
Status = ForwardIrpAndWait(HubDeviceExtension->LowerDeviceObject, Irp);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
// failed to start pdo
|
|
|
|
|
DPRINT1("Failed to start the RootHub PDO\n");
|
2017-01-27 11:09:36 +00:00
|
|
|
|
goto cleanup;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// Get the current number of hubs
|
|
|
|
|
Status = SubmitRequestToRootHub(RootHubDeviceObject,
|
|
|
|
|
IOCTL_INTERNAL_USB_GET_HUB_COUNT,
|
|
|
|
|
&HubDeviceExtension->NumberOfHubs, NULL);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
// failed to get number of hubs
|
|
|
|
|
DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT failed with %x\n", Status);
|
2017-01-27 11:09:36 +00:00
|
|
|
|
goto cleanup;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// Get the Hub Interface
|
|
|
|
|
Status = QueryInterface(RootHubDeviceObject,
|
|
|
|
|
USB_BUS_INTERFACE_HUB_GUID,
|
|
|
|
|
sizeof(USB_BUS_INTERFACE_HUB_V5),
|
|
|
|
|
USB_BUSIF_HUB_VERSION_5,
|
|
|
|
|
(PVOID)&HubDeviceExtension->HubInterface);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
// failed to get root hub interface
|
|
|
|
|
DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status);
|
2017-01-27 11:09:36 +00:00
|
|
|
|
goto cleanup;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
2011-05-07 14:49:02 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
HubInterfaceBusContext = HubDeviceExtension->HubInterface.BusContext;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// Get the USBDI Interface
|
|
|
|
|
Status = QueryInterface(RootHubDeviceObject,
|
|
|
|
|
USB_BUS_INTERFACE_USBDI_GUID,
|
|
|
|
|
sizeof(USB_BUS_INTERFACE_USBDI_V2),
|
|
|
|
|
USB_BUSIF_USBDI_VERSION_2,
|
|
|
|
|
(PVOID)&HubDeviceExtension->UsbDInterface);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
// failed to get usbdi interface
|
|
|
|
|
DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status);
|
2017-01-27 11:09:36 +00:00
|
|
|
|
goto cleanup;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
2011-05-07 14:49:02 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// Get Root Hub Device Handle
|
|
|
|
|
Status = SubmitRequestToRootHub(RootHubDeviceObject,
|
|
|
|
|
IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE,
|
|
|
|
|
&HubDeviceExtension->RootHubHandle,
|
|
|
|
|
NULL);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
// failed
|
|
|
|
|
DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE failed with status 0x%08lx\n", Status);
|
2017-01-27 11:09:36 +00:00
|
|
|
|
goto cleanup;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
//
|
|
|
|
|
// Get Hub Device Information
|
|
|
|
|
//
|
|
|
|
|
Status = HubDeviceExtension->HubInterface.QueryDeviceInformation(HubInterfaceBusContext,
|
|
|
|
|
HubDeviceExtension->RootHubHandle,
|
|
|
|
|
&HubDeviceExtension->DeviceInformation,
|
|
|
|
|
sizeof(USB_DEVICE_INFORMATION_0),
|
|
|
|
|
&Result);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2014-11-02 11:30:14 +00:00
|
|
|
|
DPRINT("Status %x, Result 0x%08lx\n", Status, Result);
|
|
|
|
|
DPRINT("InformationLevel %x\n", HubDeviceExtension->DeviceInformation.InformationLevel);
|
|
|
|
|
DPRINT("ActualLength %x\n", HubDeviceExtension->DeviceInformation.ActualLength);
|
|
|
|
|
DPRINT("PortNumber %x\n", HubDeviceExtension->DeviceInformation.PortNumber);
|
|
|
|
|
DPRINT("DeviceDescriptor %x\n", HubDeviceExtension->DeviceInformation.DeviceDescriptor);
|
|
|
|
|
DPRINT("HubAddress %x\n", HubDeviceExtension->DeviceInformation.HubAddress);
|
|
|
|
|
DPRINT("NumberofPipes %x\n", HubDeviceExtension->DeviceInformation.NumberOfOpenPipes);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// Get Root Hubs Device Descriptor
|
|
|
|
|
UsbBuildGetDescriptorRequest(Urb,
|
|
|
|
|
sizeof(Urb->UrbControlDescriptorRequest),
|
|
|
|
|
USB_DEVICE_DESCRIPTOR_TYPE,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
&HubDeviceExtension->HubDeviceDescriptor,
|
|
|
|
|
NULL,
|
|
|
|
|
sizeof(USB_DEVICE_DESCRIPTOR),
|
|
|
|
|
NULL);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// set device handle
|
|
|
|
|
Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// get hub device descriptor
|
|
|
|
|
Status = SubmitRequestToRootHub(RootHubDeviceObject,
|
|
|
|
|
IOCTL_INTERNAL_USB_SUBMIT_URB,
|
|
|
|
|
Urb,
|
|
|
|
|
NULL);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
// failed to get device descriptor of hub
|
|
|
|
|
DPRINT1("Failed to get HubDeviceDescriptor!\n");
|
2017-01-27 11:09:36 +00:00
|
|
|
|
goto cleanup;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// build configuration request
|
|
|
|
|
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);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// set device handle
|
|
|
|
|
Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// request configuration descriptor
|
|
|
|
|
Status = SubmitRequestToRootHub(RootHubDeviceObject,
|
|
|
|
|
IOCTL_INTERNAL_USB_SUBMIT_URB,
|
|
|
|
|
Urb,
|
|
|
|
|
NULL);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
// failed to get configuration descriptor
|
|
|
|
|
DPRINT1("Failed to get RootHub Configuration with status %x\n", Status);
|
2017-01-27 11:09:36 +00:00
|
|
|
|
goto cleanup;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// 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
|
|
|
|
|
|
|
|
|
|
// get hub information
|
|
|
|
|
Status = HubDeviceExtension->HubInterface.GetExtendedHubInformation(HubInterfaceBusContext,
|
|
|
|
|
RootHubDeviceObject,
|
|
|
|
|
&HubDeviceExtension->UsbExtHubInfo,
|
|
|
|
|
sizeof(USB_EXTHUB_INFORMATION_0),
|
|
|
|
|
&Result);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
// failed to get hub information
|
|
|
|
|
DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n");
|
2017-01-27 11:09:36 +00:00
|
|
|
|
goto cleanup;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
2011-05-07 14:49:02 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
if (!HubDeviceExtension->UsbExtHubInfo.NumberOfPorts)
|
|
|
|
|
{
|
|
|
|
|
// bogus port driver
|
|
|
|
|
DPRINT1("Failed to retrieve the number of ports\n");
|
2017-01-27 11:09:36 +00:00
|
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
|
goto cleanup;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
2011-05-07 14:49:02 +00:00
|
|
|
|
|
2014-11-02 11:30:14 +00:00
|
|
|
|
DPRINT("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension->UsbExtHubInfo.NumberOfPorts);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
|
|
// set device handle
|
|
|
|
|
Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
|
|
|
|
|
|
|
|
|
|
// send request
|
|
|
|
|
Status = SubmitRequestToRootHub(RootHubDeviceObject,
|
|
|
|
|
IOCTL_INTERNAL_USB_SUBMIT_URB,
|
|
|
|
|
Urb,
|
|
|
|
|
NULL);
|
2011-05-04 12:58:42 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to get Hub Descriptor!\n");
|
2017-01-27 11:09:36 +00:00
|
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
|
goto cleanup;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sanity checks
|
|
|
|
|
ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorLength == sizeof(USB_HUB_DESCRIPTOR));
|
|
|
|
|
ASSERT(HubDeviceExtension->HubDescriptor.bNumberOfPorts == HubDeviceExtension->UsbExtHubInfo.NumberOfPorts);
|
|
|
|
|
ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorType == 0x29);
|
|
|
|
|
|
|
|
|
|
// build get status request
|
|
|
|
|
HubStatus = 0;
|
|
|
|
|
UsbBuildGetStatusRequest(Urb,
|
|
|
|
|
URB_FUNCTION_GET_STATUS_FROM_DEVICE,
|
|
|
|
|
0,
|
|
|
|
|
&HubStatus,
|
|
|
|
|
0,
|
|
|
|
|
NULL);
|
|
|
|
|
// set device handle
|
|
|
|
|
Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
|
|
|
|
|
|
|
|
|
|
// send request
|
|
|
|
|
Status = SubmitRequestToRootHub(RootHubDeviceObject,
|
|
|
|
|
IOCTL_INTERNAL_USB_SUBMIT_URB,
|
|
|
|
|
Urb,
|
|
|
|
|
NULL);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
// failed to get hub status
|
|
|
|
|
DPRINT1("Failed to get Hub Status!\n");
|
2017-01-27 11:09:36 +00:00
|
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
|
goto cleanup;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
2011-05-04 12:58:42 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub
|
|
|
|
|
HubDeviceExtension->PortStatusChange = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
sizeof(ULONG) * HubDeviceExtension->UsbExtHubInfo.NumberOfPorts,
|
|
|
|
|
USB_HUB_TAG);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
if (!HubDeviceExtension->PortStatusChange)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to allocate pool for PortStatusChange!\n");
|
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// Get the first Configuration Descriptor
|
|
|
|
|
Pid = USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension->HubConfigDescriptor,
|
|
|
|
|
&HubDeviceExtension->HubConfigDescriptor,
|
|
|
|
|
-1, -1, -1, -1, -1);
|
|
|
|
|
if (Pid == NULL)
|
|
|
|
|
{
|
|
|
|
|
// failed parse hub descriptor
|
|
|
|
|
DPRINT1("Failed to parse configuration descriptor\n");
|
2017-01-27 11:09:36 +00:00
|
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
|
goto cleanup;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// create configuration request
|
|
|
|
|
InterfaceList[0].InterfaceDescriptor = Pid;
|
|
|
|
|
ConfigUrb = USBD_CreateConfigurationRequestEx(&HubDeviceExtension->HubConfigDescriptor,
|
|
|
|
|
(PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList);
|
|
|
|
|
if (ConfigUrb == NULL)
|
|
|
|
|
{
|
|
|
|
|
// failed to build urb
|
|
|
|
|
DPRINT1("Failed to allocate urb\n");
|
2017-01-27 11:09:36 +00:00
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto cleanup;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// send request
|
|
|
|
|
Status = SubmitRequestToRootHub(RootHubDeviceObject,
|
|
|
|
|
IOCTL_INTERNAL_USB_SUBMIT_URB,
|
|
|
|
|
ConfigUrb,
|
|
|
|
|
NULL);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
// failed to select configuration
|
|
|
|
|
DPRINT1("Failed to select configuration with %x\n", Status);
|
2017-01-27 11:09:36 +00:00
|
|
|
|
goto cleanup;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
2011-06-01 08:31:33 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// store configuration & pipe handle
|
|
|
|
|
HubDeviceExtension->ConfigurationHandle = ConfigUrb->UrbSelectConfiguration.ConfigurationHandle;
|
|
|
|
|
HubDeviceExtension->PipeHandle = ConfigUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle;
|
|
|
|
|
DPRINT("Configuration Handle %x\n", HubDeviceExtension->ConfigurationHandle);
|
2011-05-07 14:49:02 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// check if function is available
|
|
|
|
|
if (HubDeviceExtension->UsbDInterface.IsDeviceHighSpeed)
|
|
|
|
|
{
|
|
|
|
|
// is it high speed bus
|
|
|
|
|
if (HubDeviceExtension->UsbDInterface.IsDeviceHighSpeed(HubInterfaceBusContext))
|
|
|
|
|
{
|
|
|
|
|
// initialize usb 2.0 hub
|
|
|
|
|
Status = HubDeviceExtension->HubInterface.Initialize20Hub(HubInterfaceBusContext,
|
|
|
|
|
HubDeviceExtension->RootHubHandle, 1);
|
|
|
|
|
DPRINT("Status %x\n", Status);
|
2011-05-07 14:49:02 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// FIXME handle error
|
|
|
|
|
ASSERT(Status == STATUS_SUCCESS);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-05-07 14:49:02 +00:00
|
|
|
|
|
2011-05-04 12:58:42 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// Enable power on all ports
|
|
|
|
|
DPRINT("Enabling PortPower on all ports!\n");
|
|
|
|
|
for (PortId = 1; PortId <= HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++)
|
|
|
|
|
{
|
|
|
|
|
Status = SetPortFeature(RootHubDeviceObject, PortId, PORT_POWER);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
DPRINT1("Failed to power on port %d\n", PortId);
|
2011-05-08 12:24:26 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_CONNECTION);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
DPRINT1("Failed to power on port %d\n", PortId);
|
|
|
|
|
}
|
2011-06-01 08:31:33 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// init root hub notification
|
|
|
|
|
if (HubDeviceExtension->HubInterface.RootHubInitNotification)
|
|
|
|
|
{
|
|
|
|
|
Status = HubDeviceExtension->HubInterface.RootHubInitNotification(HubInterfaceBusContext,
|
|
|
|
|
DeviceObject,
|
|
|
|
|
RootHubInitCallbackFunction);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to set callback\n");
|
2017-01-27 11:09:36 +00:00
|
|
|
|
goto cleanup;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Send the first SCE Request
|
|
|
|
|
QueryStatusChangeEndpoint(DeviceObject);
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// reset ports
|
|
|
|
|
//
|
|
|
|
|
for (PortId = 1; PortId <= HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++)
|
|
|
|
|
{
|
2011-05-04 21:45:55 +00:00
|
|
|
|
//
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// get port status
|
2011-05-07 14:49:02 +00:00
|
|
|
|
//
|
2012-02-29 17:08:32 +00:00
|
|
|
|
Status = GetPortStatusAndChange(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, &StatusChange);
|
|
|
|
|
if (NT_SUCCESS(Status))
|
2011-05-07 14:49:02 +00:00
|
|
|
|
{
|
2012-01-30 22:45:16 +00:00
|
|
|
|
//
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// is there a device connected
|
2012-01-30 22:45:16 +00:00
|
|
|
|
//
|
2012-02-29 17:08:32 +00:00
|
|
|
|
if (StatusChange.Status & USB_PORT_STATUS_CONNECT)
|
2012-01-25 03:39:57 +00:00
|
|
|
|
{
|
|
|
|
|
//
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// reset port
|
2012-01-25 03:39:57 +00:00
|
|
|
|
//
|
2012-02-29 17:08:32 +00:00
|
|
|
|
Status = SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_RESET);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to reset on port %d\n", PortId);
|
|
|
|
|
}
|
|
|
|
|
else
|
2012-01-25 03:39:57 +00:00
|
|
|
|
{
|
|
|
|
|
//
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// wait for the reset to be handled since we want to enumerate synchronously
|
2012-01-25 03:39:57 +00:00
|
|
|
|
//
|
2012-02-29 17:08:32 +00:00
|
|
|
|
KeWaitForSingleObject(&HubDeviceExtension->ResetComplete,
|
|
|
|
|
Executive,
|
|
|
|
|
KernelMode,
|
|
|
|
|
FALSE,
|
|
|
|
|
NULL);
|
|
|
|
|
KeClearEvent(&HubDeviceExtension->ResetComplete);
|
2012-01-25 03:39:57 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2011-05-07 14:49:02 +00:00
|
|
|
|
}
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2011-05-07 14:49:02 +00:00
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// free urb
|
|
|
|
|
ExFreePool(Urb);
|
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
// free ConfigUrb
|
|
|
|
|
ExFreePool(ConfigUrb);
|
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
// done
|
|
|
|
|
return Status;
|
2017-01-27 11:09:36 +00:00
|
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
|
if (Urb)
|
|
|
|
|
ExFreePool(Urb);
|
|
|
|
|
|
|
|
|
|
// Dereference interfaces
|
|
|
|
|
if (HubDeviceExtension->HubInterface.Size)
|
|
|
|
|
HubDeviceExtension->HubInterface.InterfaceDereference(HubDeviceExtension->HubInterface.BusContext);
|
|
|
|
|
|
|
|
|
|
if (HubDeviceExtension->UsbDInterface.Size)
|
|
|
|
|
HubDeviceExtension->UsbDInterface.InterfaceDereference(HubDeviceExtension->UsbDInterface.BusContext);
|
|
|
|
|
|
|
|
|
|
if (HubDeviceExtension->PortStatusChange)
|
|
|
|
|
ExFreePool(HubDeviceExtension->PortStatusChange);
|
|
|
|
|
|
|
|
|
|
if (ConfigUrb)
|
|
|
|
|
ExFreePool(ConfigUrb);
|
|
|
|
|
|
|
|
|
|
return Status;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
|
USBHUB_FdoHandlePnp(
|
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
|
IN PIRP Irp)
|
|
|
|
|
{
|
|
|
|
|
PIO_STACK_LOCATION Stack;
|
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
2017-01-27 11:09:36 +00:00
|
|
|
|
PDEVICE_OBJECT ChildDeviceObject;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
PHUB_DEVICE_EXTENSION HubDeviceExtension;
|
2017-01-27 11:09:36 +00:00
|
|
|
|
PUSB_BUS_INTERFACE_HUB_V5 HubInterface;
|
|
|
|
|
PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
|
|
|
|
|
HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
HubInterface = &HubDeviceExtension->HubInterface;
|
2012-02-29 17:08:32 +00:00
|
|
|
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
Status = IoAcquireRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
switch (Stack->MinorFunction)
|
|
|
|
|
{
|
2017-01-27 11:09:36 +00:00
|
|
|
|
int i;
|
|
|
|
|
|
2012-02-29 17:08:32 +00:00
|
|
|
|
case IRP_MN_START_DEVICE:
|
|
|
|
|
{
|
2017-01-27 11:09:36 +00:00
|
|
|
|
DPRINT("IRP_MN_START_DEVICE\n");
|
2012-02-29 18:51:07 +00:00
|
|
|
|
if (USBHUB_IsRootHubFDO(DeviceObject))
|
|
|
|
|
{
|
|
|
|
|
// start root hub fdo
|
|
|
|
|
Status = USBHUB_FdoStartDevice(DeviceObject, Irp);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Status = USBHUB_ParentFDOStartDevice(DeviceObject, Irp);
|
|
|
|
|
}
|
2017-01-27 11:09:36 +00:00
|
|
|
|
|
|
|
|
|
SET_NEW_PNP_STATE(HubDeviceExtension->Common, Started);
|
|
|
|
|
|
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
|
IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp);
|
|
|
|
|
return Status;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
|
|
|
|
{
|
|
|
|
|
switch (Stack->Parameters.QueryDeviceRelations.Type)
|
|
|
|
|
{
|
|
|
|
|
case BusRelations:
|
|
|
|
|
{
|
|
|
|
|
PDEVICE_RELATIONS DeviceRelations = NULL;
|
2017-01-27 11:09:36 +00:00
|
|
|
|
PDEVICE_RELATIONS RelationsFromTop = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
Status = USBHUB_FdoQueryBusRelations(DeviceObject, RelationsFromTop, &DeviceRelations);
|
|
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
if (Status == STATUS_NOT_SUPPORTED)
|
|
|
|
|
{
|
|
|
|
|
// We should process this to not lose relations from top.
|
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// We should fail an IRP
|
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
|
IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp);
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
2011-05-04 01:07:21 +00:00
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
|
|
|
|
|
Irp->IoStatus.Status = Status;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case RemovalRelations:
|
|
|
|
|
{
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
|
2017-01-27 11:09:36 +00:00
|
|
|
|
break;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
}
|
|
|
|
|
default:
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
|
2011-05-04 12:58:42 +00:00
|
|
|
|
Stack->Parameters.QueryDeviceRelations.Type);
|
2017-01-27 11:09:36 +00:00
|
|
|
|
break;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-02-03 22:59:53 +00:00
|
|
|
|
case IRP_MN_QUERY_STOP_DEVICE:
|
|
|
|
|
{
|
2017-01-27 11:09:36 +00:00
|
|
|
|
//
|
|
|
|
|
// We should fail this request, because we're not handling
|
|
|
|
|
// IRP_MN_STOP_DEVICE for now.We'll receive this IRP ONLY when
|
|
|
|
|
// PnP manager rebalances resources.
|
|
|
|
|
//
|
|
|
|
|
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
|
|
|
}
|
|
|
|
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
|
|
|
|
{
|
|
|
|
|
// No action is required from FDO because it have nothing to free.
|
|
|
|
|
DPRINT("IRP_MN_QUERY_REMOVE_DEVICE\n");
|
|
|
|
|
|
|
|
|
|
SET_NEW_PNP_STATE(HubDeviceExtension->Common, RemovePending);
|
|
|
|
|
|
2012-02-03 22:59:53 +00:00
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
2017-01-27 11:09:36 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
|
|
|
|
{
|
|
|
|
|
DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n");
|
|
|
|
|
|
|
|
|
|
if (HubDeviceExtension->Common.PnPState == RemovePending)
|
|
|
|
|
RESTORE_PREVIOUS_PNP_STATE(HubDeviceExtension->Common);
|
|
|
|
|
|
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IRP_MN_SURPRISE_REMOVAL:
|
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
// We'll receive this IRP on HUB unexpected removal, or on USB
|
|
|
|
|
// controller removal from PCI port. Here we should "let know" all
|
|
|
|
|
// our children that their parent is removed and on next removal
|
|
|
|
|
// they also can be removed.
|
|
|
|
|
//
|
|
|
|
|
SET_NEW_PNP_STATE(HubDeviceExtension->Common, SurpriseRemovePending);
|
|
|
|
|
|
|
|
|
|
KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < USB_MAXCHILDREN; i++)
|
|
|
|
|
{
|
|
|
|
|
ChildDeviceObject = HubDeviceExtension->ChildDeviceObject[i];
|
|
|
|
|
if (ChildDeviceObject)
|
|
|
|
|
{
|
|
|
|
|
ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)ChildDeviceObject->DeviceObjectExtension;
|
|
|
|
|
ChildDeviceExtension->ParentDeviceObject = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
|
|
|
|
|
|
|
|
|
// This IRP can't be failed
|
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
|
break;
|
2012-02-03 22:59:53 +00:00
|
|
|
|
}
|
|
|
|
|
case IRP_MN_REMOVE_DEVICE:
|
|
|
|
|
{
|
2017-01-27 11:09:36 +00:00
|
|
|
|
DPRINT("IRP_MN_REMOVE_DEVICE\n");
|
|
|
|
|
|
|
|
|
|
SET_NEW_PNP_STATE(HubDeviceExtension->Common, Deleted);
|
|
|
|
|
|
|
|
|
|
IoReleaseRemoveLockAndWait(&HubDeviceExtension->Common.RemoveLock, Irp);
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Here we should remove all child PDOs. At this point all children
|
|
|
|
|
// received and returned from IRP_MN_REMOVE so remove synchronization
|
|
|
|
|
// isn't needed here
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < USB_MAXCHILDREN; i++)
|
|
|
|
|
{
|
|
|
|
|
ChildDeviceObject = HubDeviceExtension->ChildDeviceObject[i];
|
|
|
|
|
if (ChildDeviceObject)
|
|
|
|
|
{
|
|
|
|
|
PHUB_CHILDDEVICE_EXTENSION UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)ChildDeviceObject->DeviceExtension;
|
|
|
|
|
|
|
|
|
|
SET_NEW_PNP_STATE(UsbChildExtension->Common, Deleted);
|
|
|
|
|
|
|
|
|
|
// Remove the usb device
|
|
|
|
|
if (UsbChildExtension->UsbDeviceHandle)
|
|
|
|
|
{
|
|
|
|
|
Status = HubInterface->RemoveUsbDevice(HubInterface->BusContext, UsbChildExtension->UsbDeviceHandle, 0);
|
|
|
|
|
ASSERT(Status == STATUS_SUCCESS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Free full configuration descriptor
|
|
|
|
|
if (UsbChildExtension->FullConfigDesc)
|
|
|
|
|
ExFreePool(UsbChildExtension->FullConfigDesc);
|
|
|
|
|
|
|
|
|
|
// Free ID buffers
|
|
|
|
|
if (UsbChildExtension->usCompatibleIds.Buffer)
|
|
|
|
|
ExFreePool(UsbChildExtension->usCompatibleIds.Buffer);
|
|
|
|
|
|
|
|
|
|
if (UsbChildExtension->usDeviceId.Buffer)
|
|
|
|
|
ExFreePool(UsbChildExtension->usDeviceId.Buffer);
|
|
|
|
|
|
|
|
|
|
if (UsbChildExtension->usHardwareIds.Buffer)
|
|
|
|
|
ExFreePool(UsbChildExtension->usHardwareIds.Buffer);
|
|
|
|
|
|
|
|
|
|
if (UsbChildExtension->usInstanceId.Buffer)
|
|
|
|
|
ExFreePool(UsbChildExtension->usInstanceId.Buffer);
|
|
|
|
|
|
|
|
|
|
DPRINT("Deleting child PDO\n");
|
|
|
|
|
IoDeleteDevice(DeviceObject);
|
|
|
|
|
ChildDeviceObject = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
|
|
|
|
|
2012-02-03 22:59:53 +00:00
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
2017-01-27 11:09:36 +00:00
|
|
|
|
Status = ForwardIrpAndForget(DeviceObject, Irp);
|
2012-02-03 22:59:53 +00:00
|
|
|
|
|
|
|
|
|
IoDetachDevice(HubDeviceExtension->LowerDeviceObject);
|
2017-01-27 11:09:36 +00:00
|
|
|
|
DPRINT("Deleting FDO 0x%p\n", DeviceObject);
|
2012-02-03 22:59:53 +00:00
|
|
|
|
IoDeleteDevice(DeviceObject);
|
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
return Status;
|
2012-02-03 22:59:53 +00:00
|
|
|
|
}
|
2011-05-04 01:07:21 +00:00
|
|
|
|
case IRP_MN_QUERY_BUS_INFORMATION:
|
|
|
|
|
{
|
2017-01-27 11:09:36 +00:00
|
|
|
|
// Function drivers and filter drivers do not handle this IRP.
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
|
2011-05-04 01:07:21 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IRP_MN_QUERY_ID:
|
|
|
|
|
{
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("IRP_MN_QUERY_ID\n");
|
2017-01-27 11:09:36 +00:00
|
|
|
|
// Function drivers and filter drivers do not handle this IRP.
|
2011-05-04 01:07:21 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IRP_MN_QUERY_CAPABILITIES:
|
|
|
|
|
{
|
2017-01-27 11:09:36 +00:00
|
|
|
|
//
|
|
|
|
|
// If a function or filter driver does not handle this IRP, it
|
|
|
|
|
// should pass that down.
|
|
|
|
|
//
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
|
2011-05-04 01:07:21 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
{
|
2012-02-12 02:53:34 +00:00
|
|
|
|
DPRINT(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack->MinorFunction);
|
2017-01-27 11:09:36 +00:00
|
|
|
|
break;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2011-05-04 12:58:42 +00:00
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
Status = ForwardIrpAndForget(DeviceObject, Irp);
|
|
|
|
|
IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp);
|
2011-05-04 01:07:21 +00:00
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
|
USBHUB_FdoHandleDeviceControl(
|
2011-05-04 12:58:42 +00:00
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
|
IN PIRP Irp)
|
2011-05-04 01:07:21 +00:00
|
|
|
|
{
|
2012-10-24 15:40:46 +00:00
|
|
|
|
PIO_STACK_LOCATION IoStack;
|
|
|
|
|
NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
|
|
|
|
|
PUSB_NODE_INFORMATION NodeInformation;
|
|
|
|
|
PHUB_DEVICE_EXTENSION HubDeviceExtension;
|
|
|
|
|
PUSB_NODE_CONNECTION_INFORMATION NodeConnectionInfo;
|
|
|
|
|
PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
|
|
|
|
|
PUSB_NODE_CONNECTION_DRIVERKEY_NAME NodeKey;
|
2012-10-25 15:36:09 +00:00
|
|
|
|
PUSB_NODE_CONNECTION_NAME ConnectionName;
|
2012-10-24 15:40:46 +00:00
|
|
|
|
ULONG Index, Length;
|
|
|
|
|
|
|
|
|
|
// get stack location
|
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
|
|
|
|
|
|
// get device extension
|
|
|
|
|
HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
Status = IoAcquireRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Prevent handling of control requests in remove pending state
|
|
|
|
|
if (HubDeviceExtension->Common.PnPState == RemovePending)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("[USBHUB] Request for removed device object %p\n", DeviceObject);
|
|
|
|
|
Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
|
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
|
IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp);
|
|
|
|
|
return STATUS_DEVICE_NOT_CONNECTED;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-24 15:40:46 +00:00
|
|
|
|
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USB_GET_NODE_INFORMATION)
|
|
|
|
|
{
|
|
|
|
|
// is the buffer big enough
|
|
|
|
|
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(USB_NODE_INFORMATION))
|
|
|
|
|
{
|
|
|
|
|
// buffer too small
|
|
|
|
|
Status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// get buffer
|
|
|
|
|
NodeInformation = (PUSB_NODE_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
|
|
|
|
|
|
// sanity check
|
|
|
|
|
ASSERT(NodeInformation);
|
|
|
|
|
|
|
|
|
|
// init buffer
|
|
|
|
|
NodeInformation->NodeType = UsbHub;
|
|
|
|
|
RtlCopyMemory(&NodeInformation->u.HubInformation.HubDescriptor, &HubDeviceExtension->HubDescriptor, sizeof(USB_HUB_DESCRIPTOR));
|
|
|
|
|
|
|
|
|
|
// FIXME is hub powered
|
|
|
|
|
NodeInformation->u.HubInformation.HubIsBusPowered = TRUE;
|
|
|
|
|
|
|
|
|
|
// done
|
|
|
|
|
Irp->IoStatus.Information = sizeof(USB_NODE_INFORMATION);
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USB_GET_NODE_CONNECTION_INFORMATION)
|
|
|
|
|
{
|
|
|
|
|
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(USB_NODE_CONNECTION_INFORMATION))
|
|
|
|
|
{
|
|
|
|
|
// buffer too small
|
|
|
|
|
Status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// get node connection info
|
|
|
|
|
NodeConnectionInfo = (PUSB_NODE_CONNECTION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
|
|
|
|
|
|
// sanity checks
|
|
|
|
|
ASSERT(NodeConnectionInfo);
|
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
2012-10-24 15:40:46 +00:00
|
|
|
|
for(Index = 0; Index < USB_MAXCHILDREN; Index++)
|
|
|
|
|
{
|
|
|
|
|
if (HubDeviceExtension->ChildDeviceObject[Index] == NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// get child device extension
|
|
|
|
|
ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)HubDeviceExtension->ChildDeviceObject[Index]->DeviceExtension;
|
|
|
|
|
|
|
|
|
|
if (ChildDeviceExtension->PortNumber != NodeConnectionInfo->ConnectionIndex)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// init node connection info
|
|
|
|
|
RtlCopyMemory(&NodeConnectionInfo->DeviceDescriptor, &ChildDeviceExtension->DeviceDesc, sizeof(USB_DEVICE_DESCRIPTOR));
|
|
|
|
|
NodeConnectionInfo->CurrentConfigurationValue = ChildDeviceExtension->FullConfigDesc->bConfigurationValue;
|
|
|
|
|
NodeConnectionInfo->DeviceIsHub = FALSE; //FIXME support hubs
|
|
|
|
|
NodeConnectionInfo->LowSpeed = ChildDeviceExtension->DeviceInformation.DeviceSpeed == UsbLowSpeed;
|
|
|
|
|
NodeConnectionInfo->DeviceAddress = ChildDeviceExtension->DeviceInformation.DeviceAddress;
|
|
|
|
|
NodeConnectionInfo->NumberOfOpenPipes = ChildDeviceExtension->DeviceInformation.NumberOfOpenPipes;
|
|
|
|
|
NodeConnectionInfo->ConnectionStatus = DeviceConnected; //FIXME
|
|
|
|
|
|
|
|
|
|
if (NodeConnectionInfo->NumberOfOpenPipes)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Need to copy pipe information\n");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2017-01-27 11:09:36 +00:00
|
|
|
|
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
2012-10-24 15:40:46 +00:00
|
|
|
|
// done
|
|
|
|
|
Irp->IoStatus.Information = sizeof(USB_NODE_INFORMATION);
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME)
|
|
|
|
|
{
|
|
|
|
|
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(USB_NODE_CONNECTION_INFORMATION))
|
|
|
|
|
{
|
|
|
|
|
// buffer too small
|
|
|
|
|
Status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// get node connection info
|
|
|
|
|
NodeKey = (PUSB_NODE_CONNECTION_DRIVERKEY_NAME)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
|
|
|
|
|
|
// sanity checks
|
|
|
|
|
ASSERT(NodeKey);
|
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
2012-10-24 15:40:46 +00:00
|
|
|
|
for(Index = 0; Index < USB_MAXCHILDREN; Index++)
|
|
|
|
|
{
|
|
|
|
|
if (HubDeviceExtension->ChildDeviceObject[Index] == NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// get child device extension
|
|
|
|
|
ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)HubDeviceExtension->ChildDeviceObject[Index]->DeviceExtension;
|
|
|
|
|
|
|
|
|
|
if (ChildDeviceExtension->PortNumber != NodeKey->ConnectionIndex)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// get driver key
|
|
|
|
|
Status = IoGetDeviceProperty(HubDeviceExtension->ChildDeviceObject[Index], DevicePropertyDriverKeyName,
|
|
|
|
|
IoStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME),
|
|
|
|
|
NodeKey->DriverKeyName,
|
|
|
|
|
&Length);
|
|
|
|
|
|
|
|
|
|
if (Status == STATUS_BUFFER_TOO_SMALL)
|
|
|
|
|
{
|
|
|
|
|
// normalize status
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Length + sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
|
|
|
|
|
{
|
|
|
|
|
// terminate node key name
|
2012-10-25 15:36:09 +00:00
|
|
|
|
NodeKey->DriverKeyName[0] = UNICODE_NULL;
|
2012-10-24 15:40:46 +00:00
|
|
|
|
Irp->IoStatus.Information = sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// result size
|
|
|
|
|
Irp->IoStatus.Information = Length + sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// length of driver name
|
|
|
|
|
NodeKey->ActualLength = Length + sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2017-01-27 11:09:36 +00:00
|
|
|
|
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
|
2012-10-24 15:40:46 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2012-10-25 15:36:09 +00:00
|
|
|
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USB_GET_NODE_CONNECTION_NAME)
|
|
|
|
|
{
|
|
|
|
|
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(USB_NODE_CONNECTION_NAME))
|
|
|
|
|
{
|
|
|
|
|
// buffer too small
|
|
|
|
|
Status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// FIXME support hubs
|
|
|
|
|
ConnectionName = (PUSB_NODE_CONNECTION_NAME)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
|
ConnectionName->ActualLength = 0;
|
|
|
|
|
ConnectionName->NodeName[0] = UNICODE_NULL;
|
|
|
|
|
|
|
|
|
|
// done
|
|
|
|
|
Irp->IoStatus.Information = sizeof(USB_NODE_CONNECTION_NAME);
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-10-24 15:40:46 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2014-11-02 11:30:14 +00:00
|
|
|
|
DPRINT1("UNIMPLEMENTED FdoHandleDeviceControl IoCtl %x InputBufferLength %x OutputBufferLength %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode,
|
2012-10-24 15:40:46 +00:00
|
|
|
|
IoStack->Parameters.DeviceIoControl.InputBufferLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// finish irp
|
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
|
|
2017-01-27 11:09:36 +00:00
|
|
|
|
IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp);
|
2012-10-24 15:40:46 +00:00
|
|
|
|
return Status;
|
2011-05-04 01:07:21 +00:00
|
|
|
|
}
|
|
|
|
|
|