USBCCGP 总线过滤驱动接口
2021-09-15
316
0
总线驱动或过滤驱动的接口其实就是一个USBC_DEVICE_CONFIGURATION_INTERFACE_V1
的结构体,其用于创建PDO.
#define USBC_DEVICE_CONFIGURATION_INTERFACE_VERSION_1 0x0001
typedef struct _USBC_DEVICE_CONFIGURATION_INTERFACE_V1 {
USHORT Size;
USHORT Version;
PVOID Context;
PINTERFACE_REFERENCE InterfaceReference;
PINTERFACE_DEREFERENCE InterfaceDereference;
USBC_START_DEVICE_CALLBACK StartDeviceCallback;
USBC_PDO_ENABLE_CALLBACK PdoEnableCallback;
PVOID Reserved[7];
} USBC_DEVICE_CONFIGURATION_INTERFACE_V1, *PUSBC_DEVICE_CONFIGURATION_INTERFACE_V1;
这块功能一般是不用的,除非我们的所定制。
这个接口是通过专门的IRP实现的,函数代码如下:
NTSTATUS
USBCCGP_QueryInterface(
IN PDEVICE_OBJECT DeviceObject,
OUT PUSBC_DEVICE_CONFIGURATION_INTERFACE_V1 BusInterface)
{
KEVENT Event;
NTSTATUS Status;
PIRP Irp;
IO_STATUS_BLOCK IoStatus;
PIO_STACK_LOCATION Stack;
/* Sanity checks */
ASSERT(DeviceObject);
/* Initialize event */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
/* Init interface */
RtlZeroMemory(BusInterface, sizeof(USBC_DEVICE_CONFIGURATION_INTERFACE_V1));
BusInterface->Version = USBC_DEVICE_CONFIGURATION_INTERFACE_VERSION_1;
BusInterface->Size = sizeof(USBC_DEVICE_CONFIGURATION_INTERFACE_V1);
/* Create irp */
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
DeviceObject,
NULL,
0,
NULL,
&Event,
&IoStatus);
//
// was irp built
//
if (Irp == NULL)
{
//
// no memory
//
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// initialize request
//
Stack = IoGetNextIrpStackLocation(Irp);
Stack->MajorFunction = IRP_MJ_PNP;
Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
Stack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
Stack->Parameters.QueryInterface.InterfaceType = (LPGUID)&USB_BUS_INTERFACE_USBC_CONFIGURATION_GUID;
Stack->Parameters.QueryInterface.Version = 2;
Stack->Parameters.QueryInterface.Interface = (PINTERFACE)&BusInterface;
Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
//
// call driver
//
Status = IoCallDriver(DeviceObject, Irp);
//
// did operation complete
//
if (Status == STATUS_PENDING)
{
//
// wait for completion
//
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
//
// collect status
//
Status = IoStatus.Status;
}
return Status;
}
可以看到,和以前的一样,就是设置完成函数,调用然后等待。
使用接口枚举子设备
在后面我们即将看到,子设备的枚举是通过USBCCGP_EnumerateFunctions
来实现的,其第一个调用的函数就是通过USBCCGP_CustomEnumWithInterface
来枚举子设备的。
NTSTATUS
USBCCGP_CustomEnumWithInterface(
IN PDEVICE_OBJECT DeviceObject)
{
PFDO_DEVICE_EXTENSION FDODeviceExtension;
ULONG FunctionDescriptorBufferLength = 0;
NTSTATUS Status;
PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptorBuffer = NULL;
//
// get device extension
//
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(FDODeviceExtension->Common.IsFDO);
if (FDODeviceExtension->BusInterface.StartDeviceCallback == NULL)
{
//
// not supported
//
return STATUS_NOT_SUPPORTED;
}
//
// invoke callback
//
Status = FDODeviceExtension->BusInterface.StartDeviceCallback(FDODeviceExtension->DeviceDescriptor,
FDODeviceExtension->ConfigurationDescriptor,
&FunctionDescriptorBuffer,
&FunctionDescriptorBufferLength,
DeviceObject,
FDODeviceExtension->PhysicalDeviceObject);
DPRINT("USBCCGP_CustomEnumWithInterface Status %lx\n", Status);
if (!NT_SUCCESS(Status))
{
//
// failed
//
return Status;
}
DPRINT("FunctionDescriptorBufferLength %lu\n", FunctionDescriptorBufferLength);
DPRINT("FunctionDescriptorBuffer %p\n", FunctionDescriptorBuffer);
//
// assume length % function buffer size
//
ASSERT(FunctionDescriptorBufferLength);
ASSERT(FunctionDescriptorBufferLength % sizeof(USBC_FUNCTION_DESCRIPTOR) == 0);
//
// store result
//
FDODeviceExtension->FunctionDescriptor = FunctionDescriptorBuffer;
FDODeviceExtension->FunctionDescriptorCount = FunctionDescriptorBufferLength / sizeof(USBC_FUNCTION_DESCRIPTOR);
//
// success
//
return STATUS_SUCCESS;
}
可以看到,这个子设备的枚举其实就是调用下层驱动来实现的。
说明一下:
枚举设备从REACTOS代码来看,当前版本(V0.4.13)这块的代码是一个未完成的工程。
在FDO_DEVCIE_EXTENSION成员变量FunctionDescriptor中保存着所有枚举的子设备,不过可以明显地看到,接口设备、关联描述符和后面的音频描述符都是直接修改,而非累加设备的。
每个子设备的信息如下:
typedef struct _USBC_FUNCTION_DESCRIPTOR{
// The 0-based index of the function described
UCHAR FunctionNumber;
// The number of interfaces contained in this function
UCHAR NumberOfInterfaces;
// A callee allocated array of pointers into the config desc buffer passed as an input
PUSB_INTERFACE_DESCRIPTOR *InterfaceDescriptorList;
// Callee allocated PNP IDs for this PDO
UNICODE_STRING HardwareId;
UNICODE_STRING CompatibleId;
UNICODE_STRING FunctionDescription;
// Custom Flags
ULONG FunctionFlags;
PVOID Reserved;
} USBC_FUNCTION_DESCRIPTOR, *PUSBC_FUNCTION_DESCRIPTOR;
HID人机交互QQ群:564808376
UAC音频QQ群:218581009
UVC相机QQ群:331552032
BOT&UASP大容量存储QQ群:258159197
STC-USB单片机QQ群:315457461
USB技术交流QQ群2:580684376
USB技术交流QQ群:952873936