Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Before Posting... Please check out the Community Guidelines in the
Announcements and Administration Category.

Re: how to modify my usb2.0 driver to usb3.0

Tim_RobertsTim_Roberts Posts: 12,620
zhonghong200@163.com wrote:
> the bulk endpoint wMaxPacketSize is 1024bytes, and in super speed endpoint companion bMaxBurst is 1

If bMaxBurst is 1, that means it can burst 2 packets per microframe. 
So, your buffers need to be a multiple of 2048 bytes instead of a
multiple of 1024 bytes.  That's the only change needed.

--
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Tim Roberts, [email protected]
Providenza & Boekelheide, Inc.

Comments

  • Tim_RobertsTim_Roberts Posts: 12,620
    zhonghong200@163.com wrote:
    > now i want to refer the wdk usbsamp example,and modify our usb2.0 driver to usb3.0

    The usbsamp sample supports bulk streams, a silly and complicated
    concept that was added to USB 3.0 at the request of the mass storage
    folks and is used by no one else.

    Seriously, the only things you need to worry about are (a) parsing the
    new descriptors, and (b) incorporating bMaxBurst into your packet sizing
    computations.

    --
    Tim Roberts, xxxxx@probo.com
    Providenza & Boekelheide, Inc.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • hong_zhonghong_zhong Posts: 104
    thank you ,Tim Roberts.

    >>>If bMaxBurst is 1, that means it can burst 2 packets per microframe.?
    So, your buffers need to be a multiple of 2048 bytes instead of a
    multiple of 1024 bytes.? That's the only change needed.


    Do you mean that my application's buffer is a multiple of 2048 bytes? yes, my application buffer is large and is a multiple of 2048bytes, but I can not receive any packet from firmware, i use bushound capture the packet, and receive no packet. but i test in linux, it can receive packet .


    Is this a firmware issue?
  • Doron_HolanDoron_Holan Posts: 10,360
    What does the usb etw log indicate?

    Bent from my phone

    ________________________________
    From: 30061735200n behalf of
    Sent: Saturday, August 11, 2018 12:15 AM
    To: Windows System Software Devs Interest List
    Subject: RE:[ntdev] Re: how to modify my usb2.0 driver to usb3.0

    thank you ,Tim Roberts.

    >>>If bMaxBurst is 1, that means it can burst 2 packets per microframe.?
    So, your buffers need to be a multiple of 2048 bytes instead of a
    multiple of 1024 bytes.? That's the only change needed.


    Do you mean that my application's buffer is a multiple of 2048 bytes? yes, my application buffer is large and is a multiple of 2048bytes, but I can not receive any packet from firmware, i use bushound capture the packet, and receive no packet. but i test in linux, it can receive packet .


    Is this a firmware issue?







    ---
    NTDEV is sponsored by OSR

    Visit the list online at:

    MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
    Details at

    To unsubscribe, visit the List Server section of OSR Online at
  • Tim_RobertsTim_Roberts Posts: 12,620
    On Aug 11, 2018, at 12:14 AM, zhonghong200@163.com <xxxxx@lists.osr.com> wrote:
    >
    >
    >>>> If bMaxBurst is 1, that means it can burst 2 packets per microframe.ย
    > So, your buffers need to be a multiple of 2048 bytes instead of a
    > multiple of 1024 bytes.ย That's the only change needed.
    >
    >
    > Do you mean that my application's buffer is a multiple of 2048 bytes? yes, my application buffer is large and is a multiple of 2048bytes, but I can not receive any packet from firmware,

    No, the buffer in your URB needs to be a multiple of 2048 bytes. If you are passing the user's buffer directly to the URB, then yes, you'd need to enforce that. This is a restriction that some people don't realize. When you submit a "read", the device is never told how many bytes to send. It merely gets a signal that says "GO". The device is allowed to send up to and including the endpoint's max packet size (with bursting in USB 3). If you pass in a buffer shorter than that, the host controller might schedule some other device immediately after. If the device sends more than that, it can step on some other device's time. That condition is called "babble".


    > i use bushound capture the packet, and receive no packet. but i test in linux, it can receive packet .

    What error do you get back?

    Tim Roberts, xxxxx@probo.com
    Providenza & Boekelheide, Inc.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • hong_zhonghong_zhong Posts: 104
    >>>What error do you get back?

    thank you ,Tim Roberts .

    not report any errors, that is, no data can be read, I am using windbg for debugging.
  • Tim_RobertsTim_Roberts Posts: 12,620
    On Aug 13, 2018, at 7:28 PM, zhonghong200@163.com <xxxxx@lists.osr.com> wrote:
    >
    >>>> What error do you get back?
    >
    > thank you ,Tim Roberts .
    >
    > not report any errors, that is, no data can be read, I am using windbg for debugging.

    Are you saying the URBs never complete? Are you sure the hardware is capable of USB 3 operation?

    Tim Roberts, xxxxx@probo.com
    Providenza & Boekelheide, Inc.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • hong_zhonghong_zhong Posts: 104
    thank you ,Tim Roberts ,right now i use debugView print the driver log,and find the error.

    00006340 84.51743317 Drv: ReadWriteBulkEndPoints - begins
    00006341 84.51743317 Drv: Transfer length (122880) is bigger then MaximumTransferSize (65536)!
    00006342 84.51744843 Drv: ReadWriteBulkEndPoints - ends

    if (totalLength > deviceContext->MaximumTransferSize)
    {
    PSDrv_DbgPrint(1, ("Transfer length (%d) is bigger then MaximumTransferSize (%d)!\n", totalLength, deviceContext->MaximumTransferSize));
    status = STATUS_INVALID_PARAMETER;
    goto Exit;
    }



    and the driver code is :
    VOID ReadWriteBulkEndPoints(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN ULONG Length, IN WDF_REQUEST_TYPE RequestType)
    {
    PMDL newMdl = NULL;
    PMDL requestMdl = NULL;
    PURB urb = NULL;
    WDFMEMORY urbMemory;
    ULONG totalLength = Length;
    ULONG stageLength = 0;
    ULONG urbFlags = 0;
    NTSTATUS status;
    ULONG_PTR virtualAddress = 0;
    PREQUEST_CONTEXT rwContext = NULL;
    PFILE_CONTEXT fileContext = NULL;
    WDFUSBPIPE pipe;
    WDF_USB_PIPE_INFORMATION pipeInfo;
    WDF_OBJECT_ATTRIBUTES objectAttribs;
    USBD_PIPE_HANDLE usbdPipeHandle;
    PDEVICE_CONTEXT deviceContext;
    WDF_REQUEST_SEND_OPTIONS sendOptions;

    PSDrv_DbgPrint(3, ("ReadWriteBulkEndPoints - begins\n"));

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

    if (totalLength > deviceContext->MaximumTransferSize)
    {
    PSDrv_DbgPrint(1, ("Transfer length (%d) is bigger then MaximumTransferSize (%d)!\n", totalLength, deviceContext->MaximumTransferSize));
    status = STATUS_INVALID_PARAMETER;
    goto Exit;
    }

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

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

    if((WdfUsbPipeTypeBulk != pipeInfo.PipeType) && (WdfUsbPipeTypeInterrupt != pipeInfo.PipeType))
    {
    PSDrv_DbgPrint(1, ("Usbd pipe type is not bulk or interrupt! (PipeType = %d)\n", pipeInfo.PipeType));
    status = STATUS_INVALID_DEVICE_REQUEST;
    goto Exit;
    }

    rwContext = GetRequestContext(Request);

    if(RequestType == WdfRequestTypeRead)
    {
    status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl);
    if(!NT_SUCCESS(status))
    {
    PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputWdmMdl failed! (Status = %x)\n", status));
    goto Exit;
    }

    urbFlags |= USBD_TRANSFER_DIRECTION_IN;
    rwContext->Read = TRUE;
    PSDrv_DbgPrint(3, ("This is a read operation...\n"));
    }
    else
    {
    status = WdfRequestRetrieveInputWdmMdl(Request, &requestMdl);
    if(!NT_SUCCESS(status))
    {
    PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputWdmMdl failed! (Status = %x)\n", status));
    goto Exit;
    }

    urbFlags |= USBD_TRANSFER_DIRECTION_OUT;
    rwContext->Read = FALSE;
    PSDrv_DbgPrint(3, ("This is a write operation...\n"));
    }


    urbFlags |= USBD_SHORT_TRANSFER_OK;

    virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(requestMdl);

    // The transfer request is for totalLength. We can perform a max of MAX_TRANSFER_SIZE in each stage.
    if (totalLength > MAX_TRANSFER_SIZE)
    {
    stageLength = MAX_TRANSFER_SIZE;
    }
    else
    {
    stageLength = totalLength;
    }

    newMdl = IoAllocateMdl((PVOID)virtualAddress, totalLength, FALSE, FALSE, NULL);
    if (newMdl == NULL)
    {
    PSDrv_DbgPrint(1, ("IoAllocateMdl failed! (newMdl is NULL)\n"));
    status = STATUS_INSUFFICIENT_RESOURCES;
    goto Exit;
    }

    // Map the portion of user-buffer described by an mdl to another mdl
    IoBuildPartialMdl(requestMdl, newMdl, (PVOID)virtualAddress, stageLength);

    WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs);
    objectAttribs.ParentObject = Request;

    status = WdfMemoryCreate(&objectAttribs, NonPagedPool, POOL_TAG, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), &urbMemory, (PVOID*)&urb);
    if (!NT_SUCCESS(status))
    {
    PSDrv_DbgPrint(1, ("WdfMemoryCreate for urbMemory failed! (Status = %x)\n", status));
    status = STATUS_INSUFFICIENT_RESOURCES;
    goto Exit;
    }

    usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe);

    UsbBuildInterruptOrBulkTransferRequest(urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), usbdPipeHandle, NULL, newMdl, stageLength, urbFlags, NULL);

    status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request, urbMemory, NULL);
    if (!NT_SUCCESS(status))
    {
    PSDrv_DbgPrint(1, ("WdfUsbTargetPipeFormatRequestForUrb failed! (Status = %x)\n", status));
    status = STATUS_INSUFFICIENT_RESOURCES;
    goto Exit;
    }

    WdfRequestSetCompletionRoutine(Request, ReadWriteCompletion, NULL);

    // Set REQUEST_CONTEXT parameters.
    rwContext->UrbMemory = urbMemory;
    rwContext->Mdl = newMdl;
    rwContext->Length = totalLength - stageLength;
    rwContext->Numxfer = 0;
    rwContext->VirtualAddress = virtualAddress + stageLength;

    // Set the timeout
    if (fileContext->nTimeOut != 0)
    {
    WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT);
    WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions, WDF_REL_TIMEOUT_IN_MS(fileContext->nTimeOut));

    PSDrv_DbgPrint(3, ("Pipe timeout is set to: %d\n", fileContext->nTimeOut));

    if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), &sendOptions))
    {
    status = WdfRequestGetStatus(Request);
    ASSERT(!NT_SUCCESS(status));
    }
    }
    else
    {
    if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS))
    {
    status = WdfRequestGetStatus(Request);
    ASSERT(!NT_SUCCESS(status));
    }
    }

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

    if (newMdl != NULL)
    {
    IoFreeMdl(newMdl);
    }
    }

    PSDrv_DbgPrint(3, ("ReadWriteBulkEndPoints - ends\n"));

    return;
    }
  • Tim_RobertsTim_Roberts Posts: 12,620
    zhonghong200@163.com wrote:
    > thank you ,Tim Roberts ,right now i use debugView print the driver log,and find the error.
    >
    > 00006340 84.51743317 Drv: ReadWriteBulkEndPoints - begins
    > 00006341 84.51743317 Drv: Transfer length (122880) is bigger then MaximumTransferSize (65536)!
    > 00006342 84.51744843 Drv: ReadWriteBulkEndPoints - ends
    >
    > if (totalLength > deviceContext->MaximumTransferSize)
    > {
    > PSDrv_DbgPrint(1, ("Transfer length (%d) is bigger then MaximumTransferSize (%d)!\n", totalLength, deviceContext->MaximumTransferSize));
    > status = STATUS_INVALID_PARAMETER;
    > goto Exit;
    > }

    That's not so hard to figure out, is it?  As a general-purpose sample
    that could have been exploited by any number of unknown misbehaving
    clients, it puts a cap on the maximum size it will accept in a user-mode
    transfer.  The default size is ridiculously small.  If you had
    investigated this even a little, you would have seen in the code that
    you can override the default maximum transfer size in the registry.  But
    if you are actually modifying this driver for your own use, just screw
    the whole concept.  You know what your apps will supply.  Rip out the
    MaximumTransferSize checking altogether.

    --
    Tim Roberts, xxxxx@probo.com
    Providenza & Boekelheide, Inc.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!