usb hubs, hotplug support, unplug support, saving log files to disk, smt

This commit is contained in:
maksw committed 2026-06-09 09:14:24 +02:00
1 parent b838f8d83d
commit 27b31f62b6
39 files changed
+6294 -735

No files matched your search

+150
View File
@@ -0,0 +1,150 @@
// usb_composite.c - USB composite function driver and interface-PDO bus.
#include "usb.h"
DRIVER_OBJECT gUsbCompositeDriver;
static const IO_DEVICE_ID gUsbCompositeIds[] = {
{ IoBusUsb, { "USB\\COMPOSITE", sizeof("USB\\COMPOSITE") - 1 } },
};
static const IO_DRIVER_ID_TABLE gUsbCompositeIdTable = {
gUsbCompositeIds,
sizeof(gUsbCompositeIds) / sizeof(gUsbCompositeIds[0]),
};
static KSTATUS UsbCompositeCreateInterfaces(USB_COMPOSITE_EXTENSION* ext) {
if (!ext || !ext->Device || ext->InterfacesCreated)
return STATUS_SUCCESS;
XHCI_DEVICE* xdev = (XHCI_DEVICE*)ext->Device->HcdDeviceContext;
if (!xdev)
return STATUS_INVALID_PARAMETER;
KSTATUS st = UsbCreateInterfacePdos(ext->Device->Hcd, xdev, ext->Self);
if (KSUCCESS(st))
ext->InterfacesCreated = true;
return st;
}
static KSTATUS UsbCompositeForwardPnp(DEVICE_OBJECT* device, IRP* irp, KSTATUS localStatus) {
if (!KSUCCESS(localStatus)) {
IoCompleteRequest(irp, localStatus, 0);
return STATUS_PENDING;
}
return IoForwardIrpToLower(device, irp);
}
KSTATUS UsbCompositeDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
if (!device || !irp)
return STATUS_INVALID_PARAMETER;
// The composite driver owns two different device-object roles:
// * an FDO attached above a USB device PDO, and
// * interface PDOs that it creates for class drivers.
// Forwarded PnP IRPs from HID/storage land on the interface PDO, so the
// PDO must use the generic USB PDO PnP handler. Treating its
// USB_PDO_EXTENSION as USB_COMPOSITE_EXTENSION corrupts the dispatch path.
if (device->Type == DeviceObjectPhysical)
return UsbDispatchPdoPnp(device, irp);
IO_STACK_LOCATION* ios = IoGetCurrentIrpStackLocation(irp);
if (!ios || ios->MajorFunction != IRP_MJ_PNP)
return STATUS_INVALID_PARAMETER;
USB_COMPOSITE_EXTENSION* ext = (USB_COMPOSITE_EXTENSION*)device->DeviceExtension;
KSTATUS st = STATUS_SUCCESS;
switch ((IO_PNP_MINOR_FUNCTION)ios->MinorFunction) {
case IRP_MN_START_DEVICE:
device->PnpState = DevicePnpStarted;
if (ext) {
if (ext->DevicePdo)
ext->DevicePdo->PnpState = DevicePnpStarted;
ext->Started = true;
st = UsbCompositeCreateInterfaces(ext);
}
return UsbCompositeForwardPnp(device, irp, st);
case IRP_MN_QUERY_REMOVE_DEVICE:
device->PnpState = DevicePnpRemovePending;
return IoForwardIrpToLower(device, irp);
case IRP_MN_CANCEL_REMOVE_DEVICE:
device->PnpState = DevicePnpStarted;
return IoForwardIrpToLower(device, irp);
case IRP_MN_SURPRISE_REMOVAL:
device->PnpState = DevicePnpSurpriseRemoved;
if (ext)
ext->Started = false;
(void)UsbRemoveDeviceObjectChildren(device, true);
return IoForwardIrpToLower(device, irp);
case IRP_MN_REMOVE_DEVICE:
device->PnpState = DevicePnpDeleted;
if (ext) {
ext->Started = false;
(void)UsbRemoveDeviceObjectChildren(device, false);
if (ext->LowerDevice) {
KSTATUS lower = IoForwardIrpToLower(device, irp);
IoDetachDevice(device);
ext->LowerDevice = (DEVICE_OBJECT*)0;
IoDeleteDevice(device);
if (lower == STATUS_NOT_SUPPORTED) {
IoCompleteRequest(irp, STATUS_SUCCESS, 0);
return STATUS_PENDING;
}
if (lower != STATUS_PENDING && !KSUCCESS(lower)) {
IoCompleteRequest(irp, lower, 0);
return STATUS_PENDING;
}
return lower;
}
}
IoDeleteDevice(device);
IoCompleteRequest(irp, STATUS_SUCCESS, 0);
return STATUS_PENDING;
default:
return IoForwardIrpToLower(device, irp);
}
}
KSTATUS UsbCompositeAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
return STATUS_INVALID_PARAMETER;
USB_PDO_EXTENSION* pdoExt = (USB_PDO_EXTENSION*)physicalDeviceObject->DeviceExtension;
if (!pdoExt || pdoExt->Kind != UsbPdoDevice || !pdoExt->Device)
return STATUS_INVALID_PARAMETER;
DEVICE_OBJECT* fdo = (DEVICE_OBJECT*)0;
KSTATUS st = IoCreateDevice(driver, sizeof(USB_COMPOSITE_EXTENSION), &fdo);
if (!KSUCCESS(st))
return st;
(void)IoSetDeviceName(fdo, SYS_SV_LITERAL("usb-composite"));
USB_COMPOSITE_EXTENSION* ext = (USB_COMPOSITE_EXTENSION*)fdo->DeviceExtension;
ext->Self = fdo;
ext->DevicePdo = physicalDeviceObject;
ext->Device = pdoExt->Device;
ext->LowerDevice = IoAttachDeviceToDeviceStack(fdo, physicalDeviceObject);
if (!ext->LowerDevice) {
IoDeleteDevice(fdo);
return STATUS_FAILURE;
}
DbgPrint("usb: composite attached slot=%u\n", ext->Device->SlotId);
return STATUS_SUCCESS;
}
KSTATUS UsbInitializeCompositeDriver(void) {
memset(&gUsbCompositeDriver, 0, sizeof(gUsbCompositeDriver));
IoInitializeDriverObject(&gUsbCompositeDriver, SYS_SV_LITERAL("usb-composite"));
gUsbCompositeDriver.IdTable = &gUsbCompositeIdTable;
gUsbCompositeDriver.DriverAddDevice = UsbCompositeAddDevice;
gUsbCompositeDriver.MajorFunction[IRP_MJ_PNP] = UsbCompositeDispatchPnp;
gUsbCompositeDriver.MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = UsbDispatchInternalDeviceControl;
return IoRegisterDriverObject(&gUsbCompositeDriver);
}