Virtual KMDF and IPC to application in userland

I confused OP’s requirement with another who is lifting data to user-space.

Sorry.

Thomas


From:
Sent: Friday, September 10, 2010 11:11 AM
To: “Windows System Software Devs Interest List”
Subject: RE:[ntdev] Virtual KMDF and IPC to application in userland

> Alex Brown wrote:
>
>> I am now getting TransferBuffer == NULL and TransferBufferMDL
>> == NULL. Only just got to this stage… as always thanks for the
>> help. if anyone has any clues for the latest im grateful
>
> As others have already pointed, your approach #2 is correct whereas if you
> get a bulk read URB and you have no data, you store it away in a manual
> queue (for cancel safety) and complete it later once some data comes in.
>
> (I’m not sure what Thomas Divine was talking about – these are I/O’s
> coming directly from usbser and have no relation to any userspace memory,
> in fact these URBs come without any userspace app even opening the
> device…)
>
> Anyway, consider that you’re actually going to be getting two separate
> bulk read URBs here, one for the interrupt pipe (for async serial
> notifications), and one for the “data” pipe (i.e. the “OK” etc.). Are you
> responding to the right one? I don’t see how both TransferBuffer and the
> MDL can be null.
>
> Also, the URB structure is really a union, did you inspect the header to
> see if it’s really a bulk/interrupt request? Keep in mind that you’re
> going to see some endpoint zero activity (to send the various CDC ACM
> control requests) before you ever get bulk URBs.
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer

Hi Again,

I am positive both are NULL. maybe i’m not looking in the right place, I
will continue investigating.

I have a switch case that looks a bit like

switch (IncommingUrb->UrbHeader.Function)
{
case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:

break;

case URB_FUNCTION_SELECT_CONFIGURATION:

brerak;

case URB_FUNCTION_CLASS_INTERFACE:

break;

case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:

break;
}

I am assuming i’m on the right track with this.

as I said before I am at the pint where USBSER is happy and reports its
started. I can connect with hyperterm and can see chars I type via a kdprint

usbser sends me two URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFERs

one wants up to 4096 bytes
the other wants 10

}

On 10 September 2010 16:21, Thomas F. Divine wrote:

> I confused OP’s requirement with another who is lifting data to user-space.
>
> Sorry.
>
> Thomas
>
>
> --------------------------------------------------
> From:
> Sent: Friday, September 10, 2010 11:11 AM
> To: “Windows System Software Devs Interest List”
> Subject: RE:[ntdev] Virtual KMDF and IPC to application in userland
>
>
> Alex Brown wrote:
>>
>> I am now getting TransferBuffer == NULL and TransferBufferMDL
>>> == NULL. Only just got to this stage… as always thanks for the
>>> help. if anyone has any clues for the latest im grateful
>>>
>>
>> As others have already pointed, your approach #2 is correct whereas if you
>> get a bulk read URB and you have no data, you store it away in a manual
>> queue (for cancel safety) and complete it later once some data comes in.
>>
>> (I’m not sure what Thomas Divine was talking about – these are I/O’s
>> coming directly from usbser and have no relation to any userspace memory, in
>> fact these URBs come without any userspace app even opening the device…)
>>
>> Anyway, consider that you’re actually going to be getting two separate
>> bulk read URBs here, one for the interrupt pipe (for async serial
>> notifications), and one for the “data” pipe (i.e. the “OK” etc.). Are you
>> responding to the right one? I don’t see how both TransferBuffer and the
>> MDL can be null.
>>
>> Also, the URB structure is really a union, did you inspect the header to
>> see if it’s really a bulk/interrupt request? Keep in mind that you’re going
>> to see some endpoint zero activity (to send the various CDC ACM control
>> requests) before you ever get bulk URBs.
>>
>> —
>> NTDEV is sponsored by OSR
>>
>> For our schedule of WDF, WDM, debugging and other seminars visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Alex Brown wrote:

usbser sends me two
URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFERs
one wants up to 4096 bytes the other wants 10

Okay, that sounds right. The ten byte one is the interrupt pipe, and the 4096 bytes is obviously the data pipe. You’re saying both the TransferBuffer and TransferBufferMDL are both NULL???

yup

if (IncommingUrb->UrbBulkOrInterruptTransfer.TransferBuffer == NULL)
{
KdPrint((“TransferBuffer == NULL \n”));
}

if (IncommingUrb->UrbBulkOrInterruptTransfer.TransferBufferMDL == NULL)
{
KdPrint((“TransferBufferMDL == NULL \n”));
}

Ill let u guess what I see in dbgview

On 10 September 2010 16:44, wrote:

> Alex Brown wrote:
>
> > usbser sends me two
> > URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFERs
> > one wants up to 4096 bytes the other wants 10
>
> Okay, that sounds right. The ten byte one is the interrupt pipe, and the
> 4096 bytes is obviously the data pipe. You’re saying both the
> TransferBuffer and TransferBufferMDL are both NULL???
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Alex Brown wrote:

yup

Is there any way you can post your code, I wonder if some bizarre coding issue is the problem? I don’t see how transfer buffer + MDL can be NULL with non-zero transfer buffer lengths. Are you sure you’re not doing = NULL (as opposed to == NULL) somewhere and blowing them away?

Is the rest of the urb well formed?

d

dent from a phpne with no keynoard


From: Alex Brown
Sent: September 10, 2010 8:53 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Virtual KMDF and IPC to application in userland

yup

if (IncommingUrb->UrbBulkOrInterruptTransfer.TransferBuffer == NULL)
{
KdPrint((“TransferBuffer == NULL \n”));
}

if (IncommingUrb->UrbBulkOrInterruptTransfer.TransferBufferMDL == NULL)
{
KdPrint((“TransferBufferMDL == NULL \n”));
}

Ill let u guess what I see in dbgview

On 10 September 2010 16:44, > wrote:
Alex Brown wrote:

> usbser sends me two
> URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFERs
> one wants up to 4096 bytes the other wants 10

Okay, that sounds right. The ten byte one is the interrupt pipe, and the 4096 bytes is obviously the data pipe. You’re saying both the TransferBuffer and TransferBufferMDL are both NULL???


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

— NTDEV is sponsored by OSR For our schedule of WDF, WDM, debugging and other seminars visit: http://www.osr.com/seminars To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

in answer to posting code… its tricky,

Yes the rest of the urb seems to be fine

one more thing, and I feel stupid for asking, how do I tell what endpoint
the request is intended for?

On 10 September 2010 17:14, Doron Holan wrote:

> Is the rest of the urb well formed?
>
>
> d
>
> dent from a phpne with no keynoard
>
> ------------------------------
> From: Alex Brown
> Sent: September 10, 2010 8:53 AM
>
> To: Windows System Software Devs Interest List
> Subject: Re: [ntdev] Virtual KMDF and IPC to application in userland
>
> yup
>
> if (IncommingUrb->UrbBulkOrInterruptTransfer.TransferBuffer == NULL)
> {
> KdPrint((“TransferBuffer == NULL \n”));
> }
>
> if (IncommingUrb->UrbBulkOrInterruptTransfer.TransferBufferMDL == NULL)
> {
> KdPrint((“TransferBufferMDL == NULL \n”));
> }
>
> Ill let u guess what I see in dbgview
>
>
> On 10 September 2010 16:44, wrote:
>
>> Alex Brown wrote:
>>
>> > usbser sends me two
>> > URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFERs
>> > one wants up to 4096 bytes the other wants 10
>>
>> Okay, that sounds right. The ten byte one is the interrupt pipe, and the
>> 4096 bytes is obviously the data pipe. You’re saying both the
>> TransferBuffer and TransferBufferMDL are both NULL???
>>
>> —
>>
>> NTDEV is sponsored by OSR
>>
>> For our schedule of WDF, WDM, debugging and other seminars visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
>
> — NTDEV is sponsored by OSR For our schedule of WDF, WDM, debugging and
> other seminars visit: http://www.osr.com/seminars To unsubscribe, visit
> the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Alex Brown wrote:

one more thing, and I feel stupid for asking, how do I tell
what endpoint the request is intended for?

Well, you’ll want to look at the PipeHandle portion of the URB. This will correspond to whatever pipe handle you assigned to the endpoint when you responded to the select-config URB during startup.

I might be fishing in the dark here.

should I have more than one pipe for this device?

At the select configuration stage I am only setting up one pipe. so I have
two pipes. EP0 and EP!

On 10 September 2010 17:22, wrote:

> Alex Brown wrote:
>
> > one more thing, and I feel stupid for asking, how do I tell
> > what endpoint the request is intended for?
>
> Well, you’ll want to look at the PipeHandle portion of the URB. This will
> correspond to whatever pipe handle you assigned to the endpoint when you
> responded to the select-config URB during startup.
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Alex Brown wrote:

I might be fishing in the dark here.

should I have more than one pipe for this device?

At the select configuration stage I am only setting up
one pipe. so I have two pipes. EP0 and EP!

You may want to post the config descriptor that you’re feeding usbser, but you can’t be too far off because the driver is starting…

You should have four “pipes” total:

  1. The control endpoint
  2. The interrupt endpoint for async serial notifications
  3. The bulk IN endpoint for receiving data from the “device”
  4. The bulk OUT endpoint for sending data to the “device”

For 1) you get that for free, but 2), 3), and 4) all need to be present in your config descriptor, and they need unique PipeHandle’s.

This was a copy and paste job from our embedded code that I wrote a few
years ago and has been working with very few issues. Not had change to
double check it against the specs but its my first job on Monday

static const BYTE Virtual_Com_Port_ConfigDescriptor =
{
//Configuation Descriptor
0x09, // bLength: Configuation Descriptor
size
USB_CONFIGURATION_DESCRIPTOR_TYPE, // bDescriptorType: Configuration
0x43, 0x00, // wTotalLength:no of returned
bytes
0x02, // bNumInterfaces: 2 interface
0x01, // bConfigurationValue: Configuration
value
0x00, // iConfiguration: Index of string
descriptor describing the configuration
0xC0, // bmAttributes: self powered , does
not support remote wake up
0x00, // MaxPower 0 mA

//Interface Descriptor
0x09, // bLength: Interface Descriptor size
USB_INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType: Interface
0x00, // bInterfaceNumber: Number of this
Interface
0x00, // bAlternateSetting: Alternate
setting
0x01, // bNumEndpoints: One endpoints used
USB_DEVICE_CLASS_COMMUNICATIONS, // bInterfaceClass: Communication
Interface Class
0x02, // bInterfaceSubClass: Abstract
Control Model
0x01, // bInterfaceProtocol: Common AT
commands
0x00, // iInterface:

//Header Functional Descriptor
0x05, // bLength: Endpoint Descriptor size
0x24, // bDescriptorType: CS_INTERFACE
0x00, // bDescriptorSubtype: Header Func
Desc
0x10, // bcdCDC: spec release number
0x01,

//Call Managment Functional Descriptor
0x05, // bFunctionLength
0x24, // bDescriptorType: CS_INTERFACE
0x01, // bDescriptorSubtype: Call
Management Func Desc
0x00, // bmCapabilities: D0+D1
0x01, // bDataInterface: 1

//ACM Functional Descriptor
0x04, // bFunctionLength
0x24, // bDescriptorType: CS_INTERFACE
0x02, // bDescriptorSubtype: Abstract
Control Management desc
0x02, // bmCapabilities

//Union Functional Descriptor
0x05, // bFunctionLength
0x24, // bDescriptorType: CS_INTERFACE
0x06, // bDescriptorSubtype: Union func
desc
0x00, // bMasterInterface: Communication
class interface
0x01, // bSlaveInterface0: Data Class
Interface

//Endpoint 2 Descriptor
0x07, // bLength: Endpoint Descriptor size
USB_ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType: Endpoint
0x82, // bEndpointAddress: (IN2)
0x03, // bmAttributes: Interrupt
0x08, 0x00, // wMaxPacketSize:
0xFF, // bInterval:

//Data class interface descriptor
0x09, // bLength: Endpoint Descriptor size
USB_INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType:
0x01, // bInterfaceNumber: Number of this
Interface
0x00, // bAlternateSetting: Alternate
setting
0x02, // bNumEndpoints: Two endpoints used
0x0A, // bInterfaceClass: DATA_INTERFACE
0x00, // bInterfaceSubClass:
0x00, // bInterfaceProtocol:
0x00, // iInterface:

//Endpoint 3 Descriptor
0x07, // bLength: Endpoint Descriptor size
USB_ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType: Endpoint
0x03, // bEndpointAddress: (OUT3)
0x02, // bmAttributes: Bulk
0x08, 0x00, // wMaxPacketSize:
0x00, // bInterval: ignore for Bulk
transfer

//Endpoint 1 Descriptor
0x07, // bLength: Endpoint Descriptor size
USB_ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType: Endpoint
0x81, // bEndpointAddress: (IN1)
0x02, // bmAttributes: Bulk
0x08, 0x00, // wMaxPacketSize:
0x00 // bInterval
};

On 10 September 2010 17:35, wrote:

> Alex Brown wrote:
>
> > I might be fishing in the dark here.
> >
> > should I have more than one pipe for this device?
> >
> > At the select configuration stage I am only setting up
> > one pipe. so I have two pipes. EP0 and EP!
>
> You may want to post the config descriptor that you’re feeding usbser, but
> you can’t be too far off because the driver is starting…
>
> You should have four “pipes” total:
>
> 1) The control endpoint
> 2) The interrupt endpoint for async serial notifications
> 3) The bulk IN endpoint for receiving data from the “device”
> 4) The bulk OUT endpoint for sending data to the “device”
>
> For 1) you get that for free, but 2), 3), and 4) all need to be present in
> your config descriptor, and they need unique PipeHandle’s.
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Hi All,

Thanks for all the help. Once I tweaked my config descriptor I got a
configuration request for three pipes that I have unique ID’s to.

This then stopped both transfer buffers being NULL.Looks like that’s how
usbser behaves if cant work out where to send the commands.

No I just need to communicate to it from userland.

Alex

On 10 September 2010 17:52, Alex Brown wrote:

> This was a copy and paste job from our embedded code that I wrote a few
> years ago and has been working with very few issues. Not had change to
> double check it against the specs but its my first job on Monday
>
> static const BYTE Virtual_Com_Port_ConfigDescriptor =
> {
> //Configuation Descriptor
> 0x09, // bLength: Configuation Descriptor
> size
> USB_CONFIGURATION_DESCRIPTOR_TYPE, // bDescriptorType: Configuration
> 0x43, 0x00, // wTotalLength:no of returned
> bytes
> 0x02, // bNumInterfaces: 2 interface
> 0x01, // bConfigurationValue:
> Configuration value
> 0x00, // iConfiguration: Index of string
> descriptor describing the configuration
> 0xC0, // bmAttributes: self powered ,
> does not support remote wake up
> 0x00, // MaxPower 0 mA
>
> //Interface Descriptor
> 0x09, // bLength: Interface Descriptor
> size
> USB_INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType: Interface
> 0x00, // bInterfaceNumber: Number of
> this Interface
> 0x00, // bAlternateSetting: Alternate
> setting
> 0x01, // bNumEndpoints: One endpoints
> used
> USB_DEVICE_CLASS_COMMUNICATIONS, // bInterfaceClass: Communication
> Interface Class
> 0x02, // bInterfaceSubClass: Abstract
> Control Model
> 0x01, // bInterfaceProtocol: Common AT
> commands
> 0x00, // iInterface:
>
> //Header Functional Descriptor
> 0x05, // bLength: Endpoint Descriptor
> size
> 0x24, // bDescriptorType: CS_INTERFACE
> 0x00, // bDescriptorSubtype: Header Func
> Desc
> 0x10, // bcdCDC: spec release number
> 0x01,
>
> //Call Managment Functional Descriptor
> 0x05, // bFunctionLength
> 0x24, // bDescriptorType: CS_INTERFACE
> 0x01, // bDescriptorSubtype: Call
> Management Func Desc
> 0x00, // bmCapabilities: D0+D1
> 0x01, // bDataInterface: 1
>
> //ACM Functional Descriptor
> 0x04, // bFunctionLength
> 0x24, // bDescriptorType: CS_INTERFACE
> 0x02, // bDescriptorSubtype: Abstract
> Control Management desc
> 0x02, // bmCapabilities
>
> //Union Functional Descriptor
> 0x05, // bFunctionLength
> 0x24, // bDescriptorType: CS_INTERFACE
> 0x06, // bDescriptorSubtype: Union func
> desc
> 0x00, // bMasterInterface: Communication
> class interface
> 0x01, // bSlaveInterface0: Data Class
> Interface
>
> //Endpoint 2 Descriptor
> 0x07, // bLength: Endpoint Descriptor
> size
> USB_ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType: Endpoint
> 0x82, // bEndpointAddress: (IN2)
> 0x03, // bmAttributes: Interrupt
> 0x08, 0x00, // wMaxPacketSize:
> 0xFF, // bInterval:
>
> //Data class interface descriptor
> 0x09, // bLength: Endpoint Descriptor
> size
> USB_INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType:
> 0x01, // bInterfaceNumber: Number of
> this Interface
> 0x00, // bAlternateSetting: Alternate
> setting
> 0x02, // bNumEndpoints: Two endpoints
> used
> 0x0A, // bInterfaceClass: DATA_INTERFACE
> 0x00, // bInterfaceSubClass:
> 0x00, // bInterfaceProtocol:
> 0x00, // iInterface:
>
> //Endpoint 3 Descriptor
> 0x07, // bLength: Endpoint Descriptor
> size
> USB_ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType: Endpoint
> 0x03, // bEndpointAddress: (OUT3)
> 0x02, // bmAttributes: Bulk
> 0x08, 0x00, // wMaxPacketSize:
> 0x00, // bInterval: ignore for Bulk
> transfer
>
> //Endpoint 1 Descriptor
> 0x07, // bLength: Endpoint Descriptor
> size
> USB_ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType: Endpoint
> 0x81, // bEndpointAddress: (IN1)
> 0x02, // bmAttributes: Bulk
> 0x08, 0x00, // wMaxPacketSize:
> 0x00 // bInterval
> };
>
>
> On 10 September 2010 17:35, wrote:
>
>> Alex Brown wrote:
>>
>> > I might be fishing in the dark here.
>> >
>> > should I have more than one pipe for this device?
>> >
>> > At the select configuration stage I am only setting up
>> > one pipe. so I have two pipes. EP0 and EP!
>>
>> You may want to post the config descriptor that you’re feeding usbser, but
>> you can’t be too far off because the driver is starting…
>>
>> You should have four “pipes” total:
>>
>> 1) The control endpoint
>> 2) The interrupt endpoint for async serial notifications
>> 3) The bulk IN endpoint for receiving data from the “device”
>> 4) The bulk OUT endpoint for sending data to the “device”
>>
>> For 1) you get that for free, but 2), 3), and 4) all need to be present in
>> your config descriptor, and they need unique PipeHandle’s.
>>
>> —
>> NTDEV is sponsored by OSR
>>
>> For our schedule of WDF, WDM, debugging and other seminars visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
>
>