usb hubs, hotplug support, unplug support, saving log files to disk, smt
This commit is contained in:
1 parent
b838f8d83d
commit
27b31f62b6
39 files changed
+6294
-735
No files matched your search
@@ -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);
|
||||
}
|
||||
Reference in new issue
Block a user