求助:USB(HID)过滤驱动如何获取中断传输的数据呢?

RegWebName 2022-07-22 16:13:08 编辑

USB(HID)过滤驱动如何获取中断传输的数据呢?

想要开发一个USB过滤驱动,用来获取一些USB输入设备发送给主机的一些数据,比如如下的触摸的数据:
160339458183

目前有中断传输的时候,在IRP_MJ_INTERNAL_DEVICE_CONTROL的分发函数中,可以获取到IoControlCode为2228227(0x220003)。然后接下来就不知道要怎么做了。

望高手指点。

感谢!

USB中文网 2022-07-22 23:45:22 编辑

对IRP设置完成例程,当完成例程回调时可以获取到中断传输的数据。

RegWebName 2022-07-24 02:27:17 编辑

请问如下这样正确吗?好像感觉哪里不对,但是又找不到原因。

NTSTATUS IrpCompletionRoutine(IN PDEVICE_OBJECT pDeviceObj, IN PIRP pIrp, IN PVOID Context)
{
PKEVENT event = (PKEVENT)Context;
PIO_STACK_LOCATION pIoStack;
PURB pUrb;

    DBG_PRINT("OnCompletionRoutine\r\n");

    pIoStack = IoGetCurrentIrpStackLocation(pIrp);
    pUrb = (PURB)pIoStack->Parameters.Others.Argument1;

    switch (pUrb->UrbHeader.Function)
    {
    case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
    {
        ULONG Len = pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;
        ULONG i = 0;
        UCHAR* pBuf = pUrb->UrbBulkOrInterruptTransfer.TransferBuffer;

        DBG_PRINT("Len = %d\r\n", Len);
        for (i = 0; i < Len; i++)
        {
            DBG_PRINT("%02X, ", (UCHAR)pBuf[i]);
        }

        DBG_PRINT("\r\n");

    }
    break;
    }

    KeSetEvent(event, IO_NO_INCREMENT, FALSE);

    return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS DispatchInternalDeviceControl(IN PDEVICE_OBJECT pDeviceObj, IN PIRP pIrp)
{
    PDEVICE_EXTENSION pDeviceExten = (PDEVICE_EXTENSION)pDeviceObj->DeviceExtension;
    PIO_STACK_LOCATION pIoStack;
    PIO_STACK_LOCATION pIoNextStack;
    NTSTATUS status = STATUS_SUCCESS;
    PCONNECT_DATA pConnectData;

    DBG_PRINT("DispatchInternalDeviceControl\r\n");

    pIoStack = IoGetCurrentIrpStackLocation(pIrp);
    DBG_PRINT("IoControlCode = %d\r\n", pIoStack->Parameters.DeviceIoControl.IoControlCode);

#if 1
    switch (pIoStack->Parameters.DeviceIoControl.IoControlCode)
    {
    case IOCTL_INTERNAL_USB_SUBMIT_URB:
        {
            PURB pUrb = (PURB)pIoStack->Parameters.Others.Argument1;
            switch (pUrb->UrbHeader.Function)
            {
            case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
                {
                    ULONG Len = pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;
                    ULONG i = 0;
                    UCHAR* pBuf = pUrb->UrbBulkOrInterruptTransfer.TransferBuffer;
                    KEVENT event;

                    DBG_PRINT("Len = %d\r\n", Len);
                    for (i = 0; i < Len; i++)
                    {
                        DBG_PRINT("%02X, ", (UCHAR)pBuf[i]);
                    }

                    DBG_PRINT("\r\n");

                    IoCopyCurrentIrpStackLocationToNext(pIrp);
                    KeInitializeEvent(&event, NotificationEvent, FALSE);
                    IoSetCompletionRoutine(pIrp, (PIO_COMPLETION_ROUTINE)IrpCompletionRoutine, (PVOID)&event, TRUE, TRUE, TRUE);

                    status = IoCallDriver(pDeviceExten->LowerDeviceObj, pIrp);
                    if (STATUS_PENDING == status)
                    {
                        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
                        status = pIrp->IoStatus.Status;
                    }
                    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
                    return status;

                }
                break;
            }
        }
        break;

    default:
        break;
    }
#endif
    if (!NT_SUCCESS(status))
    {
        pIrp->IoStatus.Status = status;
        pIrp->IoStatus.Information = 0;
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        return status;
    }

    status = DispatchDefault(pDeviceObj, pIrp);

    return status;
}
USB中文网 2022-07-24 12:15:01 编辑

其实设置完成例程就可以了,不用增加event和KeWaitForSingleObject

RegWebName 2022-07-24 22:35:21 编辑

非常感谢站长的回复。

如果不增加event和KeWaitForSingleObject,在完成函数中好像获取不到数据,在完成函数中获取到的TransferBufferLength是0

USB中文网 2022-07-25 10:20:30 编辑

完成例程就是IRP完成时调用的,肯定会获取到数据的。除非这个IRP本身没有获取到数据。