qwerty_sz
驱动牛犊
驱动牛犊
  • 注册日期2009-04-20
  • 最后登录2012-06-28
  • 粉丝0
  • 关注0
  • 积分16分
  • 威望121点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2222回复:6

为什么驱动只能Write两次?(内详)

楼主#
更多 发布于:2010-11-24 16:49
我模仿WDK中的例子usbsamp改了个USB设备的驱动,发现在应用程序中通过WriteFile写数据时,前两次都是可以成功的,第三次应用程序就感觉想进入了死循环,没有响应了,请教这可能是哪里出了问题?下面是驱动中读写Bulk端点的代码,谢谢!
VOID
ReadWriteBulkEndPoints(
    IN WDFQUEUE         Queue,
    IN WDFREQUEST       Request,
    IN ULONG            Length,
    IN WDF_REQUEST_TYPE RequestType
    )
{
    size_t                totalLength = Length;
    size_t                stageLength = 0;
    NTSTATUS              status;
    PVOID                 virtualAddress = 0;
    PREQUEST_CONTEXT      rwContext = NULL;
    PFILE_CONTEXT         fileContext = NULL;
    WDFUSBPIPE            pipe;
    WDFMEMORY             reqMemory;
    WDFMEMORY_OFFSET      offset;
    WDF_OBJECT_ATTRIBUTES objectAttribs;
    PDEVICE_CONTEXT       deviceContext;

    UsbGateway_DbgPrint(3, ("UsbGateway_Dispatch ReadWrite - begins\n"));

    //
    // First validate input parameters.
    //
    deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));

    if (totalLength > deviceContext->MaximumTransferSize) {
        UsbGateway_DbgPrint(1, ("Transfer length > circular buffer\n"));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    if ((RequestType != WdfRequestTypeRead) &&
        (RequestType != WdfRequestTypeWrite)) {
        UsbGateway_DbgPrint(1, ("RequestType has to be either Read or Write\n"));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    //
    // Get the pipe associate with this request.
    //
    fileContext = GetFileContext(WdfRequestGetFileObject(Request));
    pipe = fileContext->Pipe;

    rwContext = GetRequestContext(Request);

    if(RequestType == WdfRequestTypeRead) {
        status = WdfRequestRetrieveOutputBuffer(Request, Length, &virtualAddress, &totalLength);
        rwContext->Read = TRUE;

    } else { //Write
        status = WdfRequestRetrieveInputBuffer(Request, Length, &virtualAddress, &totalLength);
        rwContext->Read = FALSE;
    }

    if(!NT_SUCCESS(status)){
        UsbGateway_DbgPrint(1, ("WdfRequestRetrieveInputBuffer failed\n"));
        goto Exit;
    }

    //
    // If the totalLength exceeds MAX_TRANSFER_SIZE, we will break
    // that into multiple transfer of size no more than MAX_TRANSFER_SIZE
    // in each stage.
    //
    if (totalLength > MAX_TRANSFER_SIZE) {
        stageLength = MAX_TRANSFER_SIZE;
    }
    else {
        stageLength = totalLength;
    }

    WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs);
    objectAttribs.ParentObject = Request;
    status = WdfMemoryCreatePreallocated(&objectAttribs,
                                         virtualAddress,
                                         totalLength,
                                         &reqMemory);
    if(!NT_SUCCESS(status)){
        UsbGateway_DbgPrint(1, ("WdfMemoryCreatePreallocated failed\n"));
        goto Exit;
    }

    offset.BufferOffset = 0;
    offset.BufferLength = stageLength;

    //
    // The framework format call validates to make sure that you are reading or
    // writing to the right pipe type, sets the appropriate transfer flags,
    // creates an URB and initializes the request.
    //
    if(RequestType == WdfRequestTypeRead) {

        UsbGateway_DbgPrint(3, ("Read operation\n"));
        status = WdfUsbTargetPipeFormatRequestForRead(pipe,
                                                      Request,
                                                      reqMemory,
                                                      &offset);
    } else {

        UsbGateway_DbgPrint(3, ("Write operation\n"));
        status = WdfUsbTargetPipeFormatRequestForWrite(pipe,
                                                       Request,
                                                       reqMemory,
                                                       &offset);
    }

    if (!NT_SUCCESS(status)) {
        UsbGateway_DbgPrint(1, ("WdfUsbTargetPipeFormatRequest failed 0x%x\n", status));
        goto Exit;
    }

    WdfRequestSetCompletionRoutine(
                            Request,
                            ReadWriteCompletion,
                            NULL);
    //
    // set REQUEST_CONTEXT parameters.
    //
    rwContext->Length  = totalLength - stageLength;
    rwContext->Numxfer = 0;

    //
    // Send the request asynchronously.
    //
    if (WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS) == FALSE) {
        UsbGateway_DbgPrint(1, ("WdfRequestSend failed\n"));
        status = WdfRequestGetStatus(Request);
        goto Exit;
    }



Exit:
    if (!NT_SUCCESS(status)) {
        WdfRequestCompleteWithInformation(Request, status, 0);
    }

    UsbGateway_DbgPrint(3, ("UsbGateway_DispatchReadWrite - ends\n"));

    return;
}
flever
驱动牛犊
驱动牛犊
  • 注册日期2010-03-04
  • 最后登录2011-08-13
  • 粉丝0
  • 关注0
  • 积分16分
  • 威望181点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2010-11-24 21:47
看看你的固件对不
qwerty_sz
驱动牛犊
驱动牛犊
  • 注册日期2009-04-20
  • 最后登录2012-06-28
  • 粉丝0
  • 关注0
  • 积分16分
  • 威望121点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2010-11-25 08:55
引用第1楼flever于2010-11-24 21:47发表的  :
看看你的固件对不


你好,flever,固件不对也会造成这种情况吗,为什么会让应用程序没有响应呢?
Pegram
论坛版主
论坛版主
  • 注册日期2005-12-03
  • 最后登录2013-08-23
  • 粉丝13
  • 关注5
  • 积分1333分
  • 威望4717点
  • 贡献值1点
  • 好评度78点
  • 原创分0分
  • 专家分2分
地板#
发布于:2010-11-25 18:03
给你一个建议:
建立双机调试,断到EvtIoWrite回调里面,看看阻塞在哪里。
如果根本没有进来,检查你的WDFIOQUEUE的属性,如果是序列化的,就说明前面的请求还没有结束呢。

你贴的代码太多了,有点头绪。
你的描述没有价值,我看了5分钟,不知道你自己发现了什么。别人能给你的帮助就很有限。
《寒江独钓》与《竹林蹊径》的合作作者。精通USB开发,设计了CY001 USB驱动套件(http://bbs.driverdevelop.com/read.php?tid-119314.html)。
Pegram
论坛版主
论坛版主
  • 注册日期2005-12-03
  • 最后登录2013-08-23
  • 粉丝13
  • 关注5
  • 积分1333分
  • 威望4717点
  • 贡献值1点
  • 好评度78点
  • 原创分0分
  • 专家分2分
地下室#
发布于:2010-11-25 18:09
关键是你自己的分析。
《寒江独钓》与《竹林蹊径》的合作作者。精通USB开发,设计了CY001 USB驱动套件(http://bbs.driverdevelop.com/read.php?tid-119314.html)。
qwerty_sz
驱动牛犊
驱动牛犊
  • 注册日期2009-04-20
  • 最后登录2012-06-28
  • 粉丝0
  • 关注0
  • 积分16分
  • 威望121点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2010-11-26 10:28
引用第3楼Pegram于2010-11-25 18:03发表的  :
给你一个建议:
建立双机调试,断到EvtIoWrite回调里面,看看阻塞在哪里。
如果根本没有进来,检查你的WDFIOQUEUE的属性,如果是序列化的,就说明前面的请求还没有结束呢。

你贴的代码太多了,有点头绪。
.......
---------------------------------------
不好意思,刚开始接触驱动方面的编程。

WDFIOQUEUE我采用的是WdfIoQueueDispatchParallel方式,在EvtIoWrite中,我使用的是异步方式,发现每次WdfRequestSend(Request,WdfUsbTargetPipeGetIoTarget(devCtx->UsbBulkOutPipe),WDF_NO_SEND_OPTIONS)返回的状态是STATUS_PENDING,这表明请求发送是成功的吧?但是为什么前两次可以完成IO请求,第三次就永远不会完成呢?
qwerty_sz
驱动牛犊
驱动牛犊
  • 注册日期2009-04-20
  • 最后登录2012-06-28
  • 粉丝0
  • 关注0
  • 积分16分
  • 威望121点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2010-11-30 10:56
还是没解决,感觉前两次写都是完全正常的,怎么第三次就不行了呢?抓狂!!
游客

返回顶部