none
Performing control transfer in KMDF RRS feed

  • Question

  • In my KMDF bus driver, I am simulating USB control transfer using configuration descriptor. I am aware that the Internal Device IO control that the bus driver's child PDO device receives has a URB structure in it, represented by (RequestParamaters.Parameters.Others.Arg1 ). I have some questions about this.

    1. Is the size of the buffer ( TrnasferBufferLength ) in this URB  needed to hold the descriptor, allocated by the system( usb driver stack ) itself?

    2. In order to complete this internal device io control , is it enough to copy the descriptor to the TransferBuffer of the URB directly? ie. fill the structure _URB_CONTROL_TRANSFER's TransferBufferLength, TransferBuffer, SetupPacket etc?

    3. Or ,should I populate a _URB_CONTROL_DESCRIPTOR_REQUEST structure and later copy this structure into _URB_CONTROL_TRANSFER held by the device IO control request, as below?

    			struct _URB_CONTROL_DESCRIPTOR_REQUEST Request;
    			memset(&Request, 0, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
    			Request.Hdr.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
    			Request.Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
    			Request.TransferBufferLength = configDescriptor.bLength;
    			Request.TransferBuffer = &configDescriptor;// of type USB_CONFIGURATION_DESCRIPTOR.
    			Request.Index = 0;
    			Request.DescriptorType = USB_CONFIGURATION_DESCRIPTOR_TYPE;
    			Request.LanguageId = 0;
    
    			// Create a buffer for the descriptor request.
    			status = WdfMemoryCopyFromBuffer(memoryBuffer, 0, (PVOID)&Request, sizeof(Request));
    
    			// Copy the control descriptor request to the URB of Internal Device IO .
    			status = WdfMemoryCopyToBuffer(memoryBuffer, 0, pUrb->TransferBuffer, sizeof(Request));		
    			pUrb->TransferBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
    			pUrb->Hdr.Status = USBD_STATUS_SUCCESS;
    			WdfRequestCompleteWithInformation( InternalDeviceIORequest, status, (ULONG_PTR)pUrb->TransferBufferLength);

    Which is the correct method?
    Tuesday, September 2, 2014 6:00 PM

Answers

  • 1 TransferBufferLength is the size of the buffer as specified by the caller, the usb client driver. It is not a buffer allocated by the underlying usb core stack. the underlying usb core stack copies data into the buffer

    2 Yes, you copy the descriptor to the TransferBuffer (Or the MDL if that is specified). IIRC you don't change the caller's TransferBufferLength, you set IoStatus.Information (don't remember exactly though)

    3 no. especially in your example you are passing the address of an on stack variable (&configDescriptor) back to the caller. you don't want to overwrite the caller's buffer pointer value


    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Tuesday, September 2, 2014 6:24 PM

All replies

  • 1 TransferBufferLength is the size of the buffer as specified by the caller, the usb client driver. It is not a buffer allocated by the underlying usb core stack. the underlying usb core stack copies data into the buffer

    2 Yes, you copy the descriptor to the TransferBuffer (Or the MDL if that is specified). IIRC you don't change the caller's TransferBufferLength, you set IoStatus.Information (don't remember exactly though)

    3 no. especially in your example you are passing the address of an on stack variable (&configDescriptor) back to the caller. you don't want to overwrite the caller's buffer pointer value


    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Tuesday, September 2, 2014 6:24 PM
  • Thanks Doron.

    2. I didn't get  what you meant by "you don't change the caller's TransferBufferLength".  But since the buffer is allocated by the client driver( in our case the bus driver ) shouldn't we mention TrnasferBufferLength?

    And " IoStatus.Information " is calling WdfRequestSetInformation()

    3. Even if I use the TransferBuffer of _URB_CONTROL_TRANSFER  there is this assignment. Does this buffer have to be allocated from non-paged pool and then descriptot copied to it, instead of directly assigning stack vatiable?

    Tuesday, September 2, 2014 6:48 PM
  • is your bus driver the initiator of the URB request or processing the URB request sent by the driver above you?

    2) you set TransferBufferLength as the sender of this request. the processor of this request (the one that will complete it) does not change TransferBufferLength

    3) I think you are confusing the terms, there is assignment (Foo.A = &b;) with copying of data to a buffer (RtlCopyMemory(Foo.A, &b, <size>). As the sender of the request you assign the buffer value, as the processor you copy


    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Tuesday, September 2, 2014 8:49 PM
  • Thanks Doron. My bus driver is processing URBs for control transfer( Internal Device control ) sent by a driver above( eg:usbccgp.sys).

     I have a couple more questions.

    1. I understand that the setup packet structure for standard device requests has a wLength parameter. But WDF_USB_CONTROL_SETUP_PACKET_INIT doesn't seem to initiaise this wLength paramater.But it does initialize all others.  I guess this denotes how many bytes of data is to be transfered. How does this macro handle the initialisation of wLength?

    2. Also, I am looking into handling Configuration Descriptor handling using control transfer. When the first Internal Device IO control for configuration descripto arrives, I am filling the values as below. And the TransferBufferLength provided by the URB associated with this Internal IOCLT( ie.one that arrives first) is 9 bytes-which is the standard config descriptor size.

    DF_USB_CONTROL_SETUP_PACKET_INIT(&setupPacket, BmRequestDeviceToHost, BmRequestToDevice, 0x6, ((2<< 8) | 1), 1
     );
    			struct _URB_CONTROL_TRANSFER* pUrb;// Just denoting this URB here. This URB actually came as part of Internal Device Control for config descriptor.
    			pUrb->Hdr.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
    			pUrb->Hdr.Length = sizeof(struct _URB_CONTROL_TRANSFER);
    			pUrb->PipeHandle = NULL;		
    			
    			pUrb->TransferBuffer = &configDescriptor; // contains the first nine bytes of config descriptor.
    			pUrb->TransferBufferLength = configDescriptor.bLength; //9 . It is about setting this buffer length that there is confusion on my side. anyway...
    			pUrb->TransferFlags = USBD_DEFAULT_PIPE_TRANSFER | USBD_TRANSFER_DIRECTION_IN;
    			size_t packetSize = sizeof(setupPacket.Packet);
    			
    			memcpy(pUrb->SetupPacket, &setupPacket.Packet, packetSize);
    			pUrb->Hdr.Status = USBD_STATUS_SUCCESS;
    Then I complete the the request associated with the above URB. Then the next time the Internal Device IO control is received again for full descriptor. But this time the TransferBufferLength of the URB associated with this Internal Device control is  again 9. But I understand that this buffer length should be configDescriptor.wTotalLength ( size of full descriptor) so that this time we can copy the full descriptor to the buffer. What could be wrong here? Is this becase of a setup packet creation issue?


    • Edited by its_me_here Wednesday, September 3, 2014 9:27 PM
    Wednesday, September 3, 2014 9:25 PM
  • I suggest you put a filter between the usbccgp FDO and a real USB PDO and see how the usbhub driver handles these URBs and sets values in the IRP.

    wLength is set by the WdfUsbDeviceSendControl APIs based on the buffer length passed in


    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, September 4, 2014 5:24 AM
  • Thanks Doron. As for setting wLength value, all we are passing only the struct _URB_CONTROL_TRANSFER structure filled in. We are not calling WdfUsbDeviceSendControl* APIs ourselves. I also tried by hardcding the values of the setuppacket array( setting 9 for wLength), but that doesnt seem to help.

     

    Also, before going deep into filters, is there anything wrong in the way I have handled filling the structures in the above code sample for config descriptor? I have done device descriptor processing in similar manner and that worked fine, leading to getting this request for  config descriptor. The configDescriptor value I have set in the above example is valid and it contains the first 9 bytes of the full descriptor( the USB_DEVICE_DESCRIPTOR structure ). I understand that the driver stack should send us the next request for the entire config descriptor based on the wTotalLength value in the PUSB_DEVICE_DESCRIPTOR structure set above.

    Monday, September 8, 2014 7:47 PM
  • Thanks Doron . The issue was actually with setting the TransferBuffer. As you suggested, the issue is now fixed by copying the data to the TransferBuffer, instead of directly assigning. . My mistake! You obtain a pointer to the buffer and copy the data to it. Also, looks like, one need not modify or set all values to the setup packet. Only the TransferBuffer and status and flags needs to be set.

    One question remains as to how the target driver ( here usbccgp.sys ) will inform the bus driver , if it doesn't process the buffer . ie. if there goes something wrong at the target driver side when it processes the URB filled and returned by the bus driver, how would it let the driver know about it? Is there anything like a Completion routine or something like that exposed to the bus driver?


    • Edited by its_me_here Friday, September 12, 2014 1:21 PM
    Friday, September 12, 2014 12:13 PM