flymonkey
驱动牛犊
驱动牛犊
  • 注册日期2003-06-09
  • 最后登录2004-09-17
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1821回复:15

我只想知道,这个参数在那里??---如何知道设备传回了多少数据??(回答对者,只要我能理解+100分)

楼主#
更多 发布于:2004-08-09 22:52
 
usb芯片内将要传回电脑的数据不固定,但小于32个字节。

现在我发一个读请求,那么怎么知道usb设备送回多少数据呢??是否主机回一直轮训,直到收到下面的“size"大小的数据才停止??

还是如果一提交这个urb后,如果收不到size大小的数据,他马上返回一个错误状态,然后我可以从什么地方知道他到底收到了多少数据??


URB urb;
UsbBuildInterruptOrBulkTransferRequest
(&urb,
sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER),
pipe,
Buffer,
NULL,
size,
USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
NULL);
status = SendAwaitUrb(fdo, &urb);//是一个发送irp的自定义函数

能回答者,送一百分!!!

[编辑 -  8/11/04 by  flymonkey]

最新喜欢:

jinghuirenjinghu...
lejianz
驱动中牛
驱动中牛
  • 注册日期2003-03-05
  • 最后登录2023-11-15
  • 粉丝0
  • 关注0
  • 积分8分
  • 威望145点
  • 贡献值0点
  • 好评度116点
  • 原创分0分
  • 专家分0分
  • 社区居民
沙发#
发布于:2004-08-10 12:04
在创建你的URB时,你的size指定你要读的字节长度,你要设置一个完成例程,标明的IoMarkIrpPending(IRP),然后返回STATUS_PENDING,在应用程序端,你用一个OVERLAPPED结构来异步读取返回来的数据。
一起交流,共同提高!
flymonkey
驱动牛犊
驱动牛犊
  • 注册日期2003-06-09
  • 最后登录2004-09-17
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-08-10 12:41
哦,谢谢,我还是不很懂,能说说具体在那个地方吗??我不需要做应该程序,做的是网卡,需要在驱动内部进行处理。

有代码更好,谢谢!!

我是说,设备将要传回主机的数据是不固定的,发出一个携带urb的irp来读,有时候读到1个,有时候10个,size 我设置为32,并允许读上来比他少的数据。那么,从什么地方能得到读取的字节数呢??(比如设备返回7个字节,那我从什么地方能知道他返回了7个呢?)

谢谢,我先加50分。

[编辑 -  8/10/04 by  flymonkey]
lejianz
驱动中牛
驱动中牛
  • 注册日期2003-03-05
  • 最后登录2023-11-15
  • 粉丝0
  • 关注0
  • 积分8分
  • 威望145点
  • 贡献值0点
  • 好评度116点
  • 原创分0分
  • 专家分0分
  • 社区居民
地板#
发布于:2004-08-10 13:20
这是D12的读写的例子,你好好看一下完成例程。

NTSTATUS
BulkUsb_DispatchReadWrite(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
/*++
 
Routine Description:

    Dispatch routine for read and write.
    This routine creates a BULKUSB_RW_CONTEXT for a read/write.
    This read/write is performed in stages of BULKUSB_MAX_TRANSFER_SIZE.
    once a stage of transfer is complete, then the irp is circulated again,
    until the requested length of tranfer is performed.

Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet

Return Value:

    NT status value

--*/
{
    PMDL                   mdl;
    PURB                   urb;
    ULONG                  totalLength;
    ULONG                  stageLength;
    ULONG                  urbFlags;
    BOOLEAN                read;
    NTSTATUS               ntStatus;
    ULONG_PTR              virtualAddress;
    PFILE_OBJECT           fileObject;
    PDEVICE_EXTENSION      deviceExtension;
    PIO_STACK_LOCATION     irpStack;
    PIO_STACK_LOCATION     nextStack;
    PBULKUSB_RW_CONTEXT    rwContext;
    PUSBD_PIPE_INFORMATION pipeInformation;

    //
    // initialize variables
    //
    urb = NULL;
    mdl = NULL;
    rwContext = NULL;
    totalLength = 0;
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    fileObject = irpStack->FileObject;
    read = (irpStack->MajorFunction == IRP_MJ_READ) ? TRUE : FALSE;
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    BulkUsb_DbgPrint(3, ("BulkUsb_DispatchReadWrite - begins\n"));

    if(deviceExtension->DeviceState != Working) {

        BulkUsb_DbgPrint(1, ("Invalid device state\n"));

        ntStatus = STATUS_INVALID_DEVICE_STATE;
        goto BulkUsb_DispatchReadWrite_Exit;
    }

    //
    // It is true that the client driver cancelled the selective suspend
    // request in the dispatch routine for create Irps.
    // But there is no guarantee that it has indeed completed.
    // so wait on the NoIdleReqPendEvent and proceed only if this event
    // is signalled.
    //
    BulkUsb_DbgPrint(3, ("Waiting on the IdleReqPendEvent\n"));
    
    //
    // make sure that the selective suspend request has been completed.
    //

    if(deviceExtension->SSEnable) {

        KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
                              Executive,
                              KernelMode,
                              FALSE,
                              NULL);
    }

    if(fileObject && fileObject->FsContext) {

        pipeInformation = fileObject->FsContext;

        if((UsbdPipeTypeInterrupt!=pipeInformation->PipeType)&&(UsbdPipeTypeBulk!=pipeInformation->PipeType)) {
            
            BulkUsb_DbgPrint(1, ("Usbd pipe type is not bulk and not interrupt\n"));

            ntStatus = STATUS_INVALID_HANDLE;
            goto BulkUsb_DispatchReadWrite_Exit;
        }
    }
    else {

        BulkUsb_DbgPrint(1, ("Invalid handle\n"));

        ntStatus = STATUS_INVALID_HANDLE;
        goto BulkUsb_DispatchReadWrite_Exit;
    }

    rwContext = (PBULKUSB_RW_CONTEXT)
                ExAllocatePool(NonPagedPool,
                               sizeof(BULKUSB_RW_CONTEXT));

    if(rwContext == NULL) {
        
        BulkUsb_DbgPrint(1, ("Failed to alloc mem for rwContext\n"));

        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
        goto BulkUsb_DispatchReadWrite_Exit;
    }

    if(Irp->MdlAddress) {

        totalLength = MmGetMdlByteCount(Irp->MdlAddress);
    }

    if(totalLength > BULKUSB_TEST_BOARD_TRANSFER_BUFFER_SIZE) {

        BulkUsb_DbgPrint(1, ("Transfer length > circular buffer\n"));

        ntStatus = STATUS_INVALID_PARAMETER;

        ExFreePool(rwContext);

        goto BulkUsb_DispatchReadWrite_Exit;
    }

    if(totalLength == 0) {

        BulkUsb_DbgPrint(1, ("Transfer data length = 0\n"));

        ntStatus = STATUS_SUCCESS;

        ExFreePool(rwContext);

        goto BulkUsb_DispatchReadWrite_Exit;
    }

    urbFlags = USBD_SHORT_TRANSFER_OK;
    virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(Irp->MdlAddress);

    if(read) {

        urbFlags |= USBD_TRANSFER_DIRECTION_IN;
        BulkUsb_DbgPrint(3, ("Read operation\n"));
    }
    else {

        urbFlags |= USBD_TRANSFER_DIRECTION_OUT;
        BulkUsb_DbgPrint(3, ("Write operation\n"));
    }

    //
    // the transfer request is for totalLength.
    // we can perform a max of BULKUSB_MAX_TRANSFER_SIZE
    // in each stage.
    //
    if(totalLength > BULKUSB_MAX_TRANSFER_SIZE) {

        stageLength = BULKUSB_MAX_TRANSFER_SIZE;
    }
    else {

        stageLength = totalLength;
    }

    mdl = IoAllocateMdl((PVOID) virtualAddress,
                        totalLength,
                        FALSE,
                        FALSE,
                        NULL);

    if(mdl == NULL) {
    
        BulkUsb_DbgPrint(1, ("Failed to alloc mem for mdl\n"));

        ntStatus = STATUS_INSUFFICIENT_RESOURCES;

        ExFreePool(rwContext);

        goto BulkUsb_DispatchReadWrite_Exit;
    }

    //
    // map the portion of user-buffer described by an mdl to another mdl
    //
    IoBuildPartialMdl(Irp->MdlAddress,
                      mdl,
                      (PVOID) virtualAddress,
                      stageLength);

    urb = ExAllocatePool(NonPagedPool,
                         sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));

    if(urb == NULL) {

        BulkUsb_DbgPrint(1, ("Failed to alloc mem for urb\n"));

        ntStatus = STATUS_INSUFFICIENT_RESOURCES;

        ExFreePool(rwContext);
        IoFreeMdl(mdl);

        goto BulkUsb_DispatchReadWrite_Exit;
    }

    UsbBuildInterruptOrBulkTransferRequest(
                            urb,
                            sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
                            pipeInformation->PipeHandle,
                            NULL,
                            mdl,
                            stageLength,
                            urbFlags,
                            NULL);

    //
    // set BULKUSB_RW_CONTEXT parameters.
    //
    
    rwContext->Urb             = urb;
    rwContext->Mdl             = mdl;
    rwContext->Length          = totalLength - stageLength;
    rwContext->Numxfer         = 0;
    rwContext->VirtualAddress  = virtualAddress + stageLength;
    rwContext->DeviceExtension = deviceExtension;

    //
    // use the original read/write irp as an internal device control irp
    //

    nextStack = IoGetNextIrpStackLocation(Irp);
    nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    nextStack->Parameters.Others.Argument1 = (PVOID) urb;
    nextStack->Parameters.DeviceIoControl.IoControlCode =
                                             IOCTL_INTERNAL_USB_SUBMIT_URB;

    IoSetCompletionRoutine(Irp,
                           (PIO_COMPLETION_ROUTINE)BulkUsb_ReadWriteCompletion,
                           rwContext,
                           TRUE,
                           TRUE,
                           TRUE);

    //
    // since we return STATUS_PENDING call IoMarkIrpPending.
    // This is the boiler plate code.
    // This may cause extra overhead of an APC for the Irp completion
    // but this is the correct thing to do.
    //

    IoMarkIrpPending(Irp);

    BulkUsb_DbgPrint(3, ("BulkUsb_DispatchReadWrite::"));
    BulkUsb_IoIncrement(deviceExtension);

    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
                            Irp);

    if(!NT_SUCCESS(ntStatus)) {

        BulkUsb_DbgPrint(1, ("IoCallDriver fails with status %X\n", ntStatus));

        //
        // if the device was yanked out, then the pipeInformation
        // field is invalid.
        // similarly if the request was cancelled, then we need not
        // invoked reset pipe/device.
        //
        if((ntStatus != STATUS_CANCELLED) &&
           (ntStatus != STATUS_DEVICE_NOT_CONNECTED)) {
            
            ntStatus = BulkUsb_ResetPipe(DeviceObject,
                                     pipeInformation);
    
            if(!NT_SUCCESS(ntStatus)) {

                BulkUsb_DbgPrint(1, ("BulkUsb_ResetPipe failed\n"));

                ntStatus = BulkUsb_ResetDevice(DeviceObject);
            }
        }
        else {

            BulkUsb_DbgPrint(3, ("ntStatus is STATUS_CANCELLED or "
                                 "STATUS_DEVICE_NOT_CONNECTED\n"));
        }
    }

    //
    // we return STATUS_PENDING and not the status returned by the lower layer.
    //
    return STATUS_PENDING;

BulkUsb_DispatchReadWrite_Exit:

    Irp->IoStatus.Status = ntStatus;
    Irp->IoStatus.Information = 0;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    BulkUsb_DbgPrint(3, ("BulkUsb_DispatchReadWrite - ends\n"));

    return ntStatus;
}

NTSTATUS
BulkUsb_ReadWriteCompletion(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp,
    IN PVOID          Context
    )
/*++
 
Routine Description:

    This is the completion routine for reads/writes
    If the irp completes with success, we check if we
    need to recirculate this irp for another stage of
    transfer. In this case return STATUS_MORE_PROCESSING_REQUIRED.
    if the irp completes in error, free all memory allocs and
    return the status.

Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet
    Context - context passed to the completion routine.

Return Value:

    NT status value

--*/
{
    ULONG               stageLength;
    NTSTATUS            ntStatus;
    PIO_STACK_LOCATION  nextStack;
    PBULKUSB_RW_CONTEXT rwContext;

    //
    // initialize variables
    //
    rwContext = (PBULKUSB_RW_CONTEXT) Context;
    ntStatus = Irp->IoStatus.Status;

    UNREFERENCED_PARAMETER(DeviceObject);
    BulkUsb_DbgPrint(3, ("BulkUsb_ReadWriteCompletion - begins\n"));

    //
    // successfully performed a stageLength of transfer.
    // check if we need to recirculate the irp.
    //
    if(NT_SUCCESS(ntStatus)) {

        if(rwContext) {

            rwContext->Numxfer +=
              rwContext->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
        
            if(rwContext->Length) {

                //
                // another stage transfer
                //
                BulkUsb_DbgPrint(3, ("Another stage transfer...\n"));

                if(rwContext->Length > BULKUSB_MAX_TRANSFER_SIZE) {
            
                    stageLength = BULKUSB_MAX_TRANSFER_SIZE;
                }
                else {
                
                    stageLength = rwContext->Length;
                }

                IoBuildPartialMdl(Irp->MdlAddress,
                                  rwContext->Mdl,
                                  (PVOID) rwContext->VirtualAddress,
                                  stageLength);
            
                //
                // reinitialize the urb
                //
                rwContext->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength
                                                                  = stageLength;
                rwContext->VirtualAddress += stageLength;
                rwContext->Length -= stageLength;

                nextStack = IoGetNextIrpStackLocation(Irp);
                nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
                nextStack->Parameters.Others.Argument1 = rwContext->Urb;
                nextStack->Parameters.DeviceIoControl.IoControlCode =
                                            IOCTL_INTERNAL_USB_SUBMIT_URB;

                IoSetCompletionRoutine(Irp,
                                       BulkUsb_ReadWriteCompletion,
                                       rwContext,
                                       TRUE,
                                       TRUE,
                                       TRUE);

                IoCallDriver(rwContext->DeviceExtension->TopOfStackDeviceObject,
                             Irp);

                return STATUS_MORE_PROCESSING_REQUIRED;
            }
            else {

                //
                // this is the last transfer
                //

                Irp->IoStatus.Information = rwContext->Numxfer;
            }
        }
    }
    else {

        BulkUsb_DbgPrint(1, ("ReadWriteCompletion - failed with status = %X\n", ntStatus));
    }
    
    if(rwContext) {

        //
        // dump rwContext
        //
        BulkUsb_DbgPrint(3, ("rwContext->Urb             = %X\n",
                             rwContext->Urb));
        BulkUsb_DbgPrint(3, ("rwContext->Mdl             = %X\n",
                             rwContext->Mdl));
        BulkUsb_DbgPrint(3, ("rwContext->Length          = %d\n",
                             rwContext->Length));
        BulkUsb_DbgPrint(3, ("rwContext->Numxfer         = %d\n",
                             rwContext->Numxfer));
        BulkUsb_DbgPrint(3, ("rwContext->VirtualAddress  = %X\n",
                             rwContext->VirtualAddress));
        BulkUsb_DbgPrint(3, ("rwContext->DeviceExtension = %X\n",
                             rwContext->DeviceExtension));

        BulkUsb_DbgPrint(3, ("BulkUsb_ReadWriteCompletion::"));
        BulkUsb_IoDecrement(rwContext->DeviceExtension);

        ExFreePool(rwContext->Urb);
        IoFreeMdl(rwContext->Mdl);
        ExFreePool(rwContext);
    }

    BulkUsb_DbgPrint(3, ("BulkUsb_ReadWriteCompletion - ends\n"));

    return ntStatus;
}

一起交流,共同提高!
flymonkey
驱动牛犊
驱动牛犊
  • 注册日期2003-06-09
  • 最后登录2004-09-17
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-08-10 13:27
啊,好兄弟,你真是我的救星,我下去看看了,谢谢谢谢!!!

分全给你。。
flymonkey
驱动牛犊
驱动牛犊
  • 注册日期2003-06-09
  • 最后登录2004-09-17
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-08-10 13:35
为什么刚才还能给分,现在给不了了,一进来就是“你未登陆论坛”

我登陆了,但只要一进usb专栏就又是“你未登陆论坛”
flymonkey
驱动牛犊
驱动牛犊
  • 注册日期2003-06-09
  • 最后登录2004-09-17
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2004-08-10 14:07
哎,我刚才看了下,还是没涉及到根本啊,这个程序已经知道了将要传回的数据大小。。。。。不是未知的,是已知的。。
lejianz
驱动中牛
驱动中牛
  • 注册日期2003-03-05
  • 最后登录2023-11-15
  • 粉丝0
  • 关注0
  • 积分8分
  • 威望145点
  • 贡献值0点
  • 好评度116点
  • 原创分0分
  • 专家分0分
  • 社区居民
7楼#
发布于:2004-08-10 14:39
其实你要求某一管道传输多少字节长度的数据,device端可以输送小于或等于你要求的长度。如果完成例程成功,它返回的值也是可以小于或等于你要求的长度。USB设备端,如果EP2长为64BYTE,但我也可以发送34个字节的数据呀,并非每次都要求64BYTE。
一起交流,共同提高!
flymonkey
驱动牛犊
驱动牛犊
  • 注册日期2003-06-09
  • 最后登录2004-09-17
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2004-08-10 15:00
它返回的值也是可以小于或等于你要求的长度


----------请问,这个返回值在什么地方??在你给的程序中的那个地方啊??
flymonkey
驱动牛犊
驱动牛犊
  • 注册日期2003-06-09
  • 最后登录2004-09-17
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2004-08-10 17:31
真是急死我了,只要回答的正确(命中要害),那么我另开新贴送分,不多了!!

帮帮我把,斑竹呢???
pengenwen
禁止发言
禁止发言
  • 注册日期2003-03-07
  • 最后登录2016-04-11
  • 粉丝0
  • 关注0
  • 积分1586分
  • 威望8380点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2004-08-10 19:03
用户被禁言,该主题自动屏蔽!
flymonkey
驱动牛犊
驱动牛犊
  • 注册日期2003-06-09
  • 最后登录2004-09-17
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2004-08-10 21:34
这个参数在那儿呢??是不是在irp->Parameters->???的某个地方,叫什么呢?
flymonkey
驱动牛犊
驱动牛犊
  • 注册日期2003-06-09
  • 最后登录2004-09-17
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2004-08-10 21:37
这个参数在那儿呢??是不是在irp的stack->Parameters->???的某个地方,叫什么呢?能说说吗??
flymonkey
驱动牛犊
驱动牛犊
  • 注册日期2003-06-09
  • 最后登录2004-09-17
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2004-08-11 00:46
大家帮个忙啊,谢谢!!
flymonkey
驱动牛犊
驱动牛犊
  • 注册日期2003-06-09
  • 最后登录2004-09-17
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2004-08-11 02:41
哈哈哈,我笑啊,我终于知道了!!!

原来在提交了一个urb后,在次读取这个urb的bufferlength域,就可以读到改变后的接收数据量,原来我还以为这个是不变的呢,原来是会改变的。哈哈

还有,读取的时候如果允许读取量少于应读量,那么在读取的数据量小于应读量的情况下,urb结构中的USBD_STATUS状态会设置一个错误,但是这个我们可以不用去管他。。因为我们本来就允许这个错误存在。

多靠了lejianz的那个例子,看来我的分送的值!!!!!!

谢谢谢谢!!
qjianhua
驱动牛犊
驱动牛犊
  • 注册日期2004-07-27
  • 最后登录2004-12-17
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2004-08-11 08:52
应该把这个收为精品帖
游客

返回顶部