Windows下USB驱动基础知识
+ -

Windows下USB驱动同步URB转IRP请求函数代码-改进版

2021-08-30 222 1

URB的同步调用一般使用:Windows下USB驱动同步URB转IRP请求函数代码 http://www.usbzh.com/article/detail-547.html
但是,在某些特定的情况下,有时会因为下底设备并没有完成而挂死。
这里提供一种超时取消IRP的方法,同时考虑到了线和切换的情况。
这里的实现机制比较巧妙,在各个完成阶段使用lock来标识当前IRP的运行状况。


    lock = 0;
    timeoutContext = ALLOCPOOL(NonPagedPool, sizeof(USB_REQUEST_TIMEOUT_CONTEXT));

    if (timeoutContext) {

        timeoutContext->event = &event;
        timeoutContext->lock = &lock;

        IoSetCompletionRoutine( irp,
                                CallDriverSyncCompletion, // context
                                timeoutContext,
                                TRUE, TRUE, TRUE);

        status = IoCallDriver(devObj, irp);

        if (status == STATUS_PENDING) {

            dueTime.QuadPart = -10000 * USB_REQUEST_TIMEOUT;

            status = KeWaitForSingleObject(
                        &event,
                        Executive,      // wait reason
                        KernelMode,
                        FALSE,          // not alertable
                        &dueTime);

            if (status == STATUS_TIMEOUT) {

                DBGWARN(("CallDriverSync timed out!\n"));

                if (InterlockedExchange(&lock, 1) == 0) {

                    //
                    // We got it to the IRP before it was completed. We can cancel
                    // the IRP without fear of losing it, as the completion routine
                    // won't let go of the IRP until we say so.
                    //
                    IoCancelIrp(irp);

                    //
                    // Release the completion routine. If it already got there,
                    // then we need to complete it ourselves. Otherwise we got
                    // through IoCancelIrp before the IRP completed entirely.
                    //
                    if (InterlockedExchange(&lock, 2) == 3) {

                        //
                        // Mark it pending because we switched threads.
                        //
                        IoMarkIrpPending(irp);
                        IoCompleteRequest(irp, IO_NO_INCREMENT);
                    }
                }

                KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);

                // Return an error code because STATUS_TIMEOUT is a successful
                // code.
                irp->IoStatus.Status = STATUS_DEVICE_DATA_ERROR;
            }
        }

        FREEPOOL(timeoutContext);

        status = irp->IoStatus.Status;

    }

完成例程的代码如下:

NTSTATUS CallDriverSyncCompletion(IN PDEVICE_OBJECT devObjOrNULL, IN PIRP irp, IN PVOID Context)
{
    PUSB_REQUEST_TIMEOUT_CONTEXT timeoutContext = Context;
    PKEVENT event = timeoutContext->event;
    PLONG lock = timeoutContext->lock;

    ASSERT(irp->IoStatus.Status != STATUS_IO_TIMEOUT);

    InterlockedExchange(lock, 3);
    KeSetEvent(event, 0, FALSE);

    return STATUS_MORE_PROCESSING_REQUIRED;
}

可以看到,完成例程的上下文包含一个事件event和一个lock的标识。
初始态lock=0,然后向下调用IRP,等待5秒钟超时后,将lock置1并返回之前的状态,如果还为0,表示真的超时,然后调用IoCancelIrp取消IRP.
取消IRP会引起IoSetCompletionRoutine的调用,在其内部一般会调用IoCompleteRequest,不过在其调用我们的完成例程CallDriverSyncCompletion由于返回了STATUS_MORE_PROCESSING_REQUIRED,表示我们再次获取了IRP的所有权,所以这里我们需要自己调用IRP的完成。
完成例程调用后,会将lock设为3,这里我们再次挂起IRP,重新完成IRP.

HID人机交互QQ群:564808376    UAC音频QQ群:218581009    UVC相机QQ群:331552032    BOT&UASP大容量存储QQ群:258159197    STC-USB单片机QQ群:315457461    USB技术交流QQ群2:580684376    USB技术交流QQ群:952873936   

0 篇笔记 写笔记

UVC 等时传输中的URB_ISOCH_TRANSFER
通过UVC规范可知,视频图像数据的读取可使用两种端点传输方式,分别为:BULK 块/批量传输方式ISO 等时/同步传输方式在Windows内核中,USB数据的读取是通过URB来进行传输的,其结构体是一个大大的共用体,根据数据传输的方式对应其不同的结构体,其内容如下:typedef _Struct_s......
IRP_MN_QUERY_CAPABILITIES和IRP_MN_QUERY_INTERFACE在USB总线驱动中的作用
在USB驱动总线开发中,IRP_MN_QUERY_BUS_INFORMATION和IRP_MN_QUERY_INTERFACE还挺重要的。对于HID设备,这两个IRP其实只要支持IRP_MN_QUERY_CAPABILITIES就行,而且这个CAPABILITIES不要额外的信息。但对于像UVC,......
USB总线FDO调用 IoInvalidateDeviceRelations通知PNP有新的设备后子设备收到的IRP
在USB FDO总线驱动中,创建了子设备PDO后,调用通知PNP管理器设备树发生了变化。这时系统会重新获取子设备关系树,然后对子设备进行信息收集,并启用。具体的过程如下:->FDO:IRP_MN_QUERY_DEVICE_RELATIONS PDO:IRP_MN_QUERY_ID......
Windows下USB驱动同步URBIRP请求函数代码
URBIRP类似,只不过一个应用于通用的Windows驱动,一个专职于USB。USB的URB的负载是IRP,其通过负载到IRP时,然后使用通用的Windows IRP请求发向下层目标USB设备。USB与IRP的关联是通过IRP的IO_STACK_LOCATION的 IoStack->Para......
Windows下USB驱动异步URBIRP请求函数代码
URB有同步请求,也有异步请求。这里微软官方提供了一个异步请求URB的代码示例// The SubmitUrbASync routine submits an URB asynchronously.//// Parameters://// Parameters:// Devic......
打印IRP_MJ_PNP所有子功能设备
PCHARPnPMinorFunctionString( UCHAR MinorFunction){ static char str[256]; switch (MinorFunction) { case IRP_MN_START_DEVICE: ......
Windows下USB驱动同步URBIRP请求函数代码-改进版
URB的同步调用一般使用:Windows下USB驱动同步URBIRP请求函数代码 http://www.usbzh.com/article/detail-547.html但是,在某些特定的情况下,有时会因为下底设备并没有完成而挂死。这里提供一种超时取消IRP的方法,同时考虑到了线和切换的情况。这里......
Windows下虚拟USB设备数据的读写请求调试笔记
到现在为止,本人已经在Windows下确切来说是Windows10 x64下开发了以下USB虚拟USB设备:USB虚拟UVC摄像头设备USB虚拟UAC麦克风设备USB虚拟HID键盘设备USB虚拟HID鼠标设备USB虚拟HID键盘鼠标复合设备USB虚拟HID单点触摸屏设备USB虚拟HID多点触摸屏......
手动分析使用BUSHOUND抓取同步传输的URB
BUSHOUND大家太熟了,使用它来进行数据抓包那不太太方便。但在BUSHOUND的抓取配置项中,有一个叫了URB的东西,我相信大家都没有选中过,因为一般来说,对WINDOWS USB驱动开发人员来说都不一定有用,更何况大家也只是用来抓取一下几个数据的输入输出,更没有必要进行USB的分析了。本人今天......
使用BUSHOUND手动分析USB控制传输的URB
USB的控制传输是最基本的传输类型,控制传输适用于设备的枚举和设备的状态控制。我里我们使用BUSHOUND来抓取USB控制传输的URB。同样的,我们使用的操作系统是Windows10 x64,和同步传输的URB抓包一样,我们先抓取数据,然后再分析数据结构。这里我插入电脑的U盘的枚举以获取设备描述符为......
使用BUSHOUND手动分析USB批量传输的URB
使用BUSHOUND抓取U盘的批量传输的URB数据,我们对其其进行数据分析:13 IN 55 53 42 53 40 0b ac 57 00 00 00 00 00 URB80 00 09 00 00 00 00 00 d8 f2 75 a0 77 7f 00 00 ......
USB摄像头同步传输的完成后URB参数
这几天不是闲来无事,一个工作的任务就是对手中一个USB摄像头进行驱动开发,并进行视频格式的转换。通过分析该USB摄像头可知,其采用的是同步传输,所以本人在开发的驱动中,使用同步的URB进行下发请求数据,然后在完成例程中获取数据。同步传输的URB本人在 手动分析使用BUSHOUND抓取同步传输的URB......
UAC麦克风同步传输的URB分析
之前写过同步传输的UVC摄像头的URB,文章名称为:手动分析使用BUSHOUND抓取同步传输的URB 。今天恰好手中有一个UVC麦克风,所以也拿来分析。也许和之前的文章有所重复,但是因为侧重点的不同,也许会有意想不到的小收获取。言归正转,我们知道,在UAC音频规范中,数据的传输不像UVC摄像头那样,......
USB摄像头同步传输H264遇到的花屏问题
以往拿到的摄像头数据传输都是批量传输,本人也只在音频驱动的开发中使用了同步传输。这次突然拿到一个摄像头,数据采用的是同步传输,本以为很简单的代码移植,却没有想到还是遇到了一个坑,自己花费了大力气来排查,在这期间自己也看了大量的资料,今天在这里做一个简单的总结。以前的摄像头拿到的USB摄像头如批量传......
USB2.0 D+和D-的差分信号J、K状态和Chirp J和Chirp K状态
J、K信号状态表示D+和D-两根差分信号数据线的数据发送状态。J、K状态在全速或者低速的模式下,当接收端收检测到D+信号线的电压比D-信号线的电压高出200mV时,表示差分信号“1”,当当接收端收检测到D-信号线的电压比D+信号线的电压高出200mV时,表示差分信号“0”.在高速的模式下,当接收......
关注公众号
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!