Losing Data During 'successful' DeviceIOControl

Hello,

I’m a beginner when it comes to driver programming, so pardon what may be a stupid question.

I’m writing an HID mini-driver (mini-port?) for a keyboard that has both a qwerty keyboard as well as a musical keyboard.

Currently, I can’t use RAWINPUT because the Music Keyboard report descriptor states that the the report size is 30 bytes, when in actuality the size ranges from 2 bytes to 30 bytes. RAWINPUT doesn’t pass the input unless there are 30 bytes received. (15 musical keys at once!)

To get around this issue, I’m writing an HID mini-driver (mini-port? semantics fail me at the moment) and I have a raw PDO created to help transfer the musical key data from the HID/Rawinput path to my own RawPDO communication path. I’m stuck at the point where I’m sending data from the KMDF driver to the User mode application. I use a DeviceIOControl() call and it comes back true with the number of bytes written that I tell it to. However, the buffer is full of 0x0s. and not the data that’s expected. An example of what is happening:

I press a key on the keyboard, it sends 0x03|0x7F|0x56. I watch the KMDF procedures (via WinDBG) from the notification that there is data from the continuous reader to when the rawPDO pops my IOCTL from the rawPDO’s queue, get the output buffer, take the data and assign 0x03|etc to the user buffer. I ‘receieve’ the data in my Windows Application and it shows 0x0|0x0|0x0.

I’m stuck, so I figured I’d ask the KMDF gurus for some help. I suspect it’s the way I’m allocating my buffers or something of the sort.

Here’s the code from the KMDF code and the application:

KMDF:

VOID
MusicKBDFilter_Send_MIDI_Data(

IN PDEVICE_EXTENSION devContext, // Device Context
IN BYTE MIDI_DATA, // Actual MIDI Data
IN size_t BufferLength //Number of Bytes

)
{
WDFREQUEST irRequest;
NTSTATUS status = STATUS_SUCCESS;
PRPDO_DEVICE_DATA myPdoData = NULL;
BYTE outMIDI_DATA[30]={0};
size_t bytesReturned=0;
size_t i;

myPdoData = PdoGetData(devContext->PdoDevice);

status = WdfIoQueueRetrieveNextRequest(myPdoData->MIDI_Queue, &irRequest);
if(NT_SUCCESS(status))
{
status = WdfRequestRetrieveUnsafeUserOutputBuffer(
irRequest,
BufferLength,
(PVOID *)outMIDI_DATA,
&bytesReturned);// BufferLength

for (i=0;i {
outMIDI_DATA[i]=MIDI_DATA[i];
}

if(NT_SUCCESS(status))
{
WdfRequestCompleteWithInformation(irRequest, STATUS_SUCCESS, bytesReturned);
}
}

return;

}

The Application Code: (not all code, but the essentials)

BYTE reportBuffer[0x20] = {0};
reportBuffer[0]=0x3;
result = DeviceIoControl(m_hDev, IOCTL_CTPKFILTER_GET_MIDI_DATA, NULL,0,reportBuffer, 0x20,&dwBytesRead,NULL);

And that returns 0x3|0x0|0x0|etc.

Thanks!

For got to post the IOCTL Constant Definition

#define IOCTL_CTPKFILTER_GET_MIDI_DATA CTL_CODE( FILE_DEVICE_USB, \
IOCTL_READMIDI, \
METHOD_NEITHER, \
FILE_READ_DATA)

Is the music keyboard keys reported through the (typing) keyboard? It should really be a USB audio device and report itself as a midi endpoint. Or at least its own top level collection. Also, do not use method_neither, use METHOD_BUFFERED.

d

Bent from my phone


From: xxxxx@huskers.unl.edumailto:xxxxx
Sent: ?5/?5/?2013 11:21 AM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: [ntdev] Losing Data During ‘successful’ DeviceIOControl

Hello,

I’m a beginner when it comes to driver programming, so pardon what may be a stupid question.

I’m writing an HID mini-driver (mini-port?) for a keyboard that has both a qwerty keyboard as well as a musical keyboard.

Currently, I can’t use RAWINPUT because the Music Keyboard report descriptor states that the the report size is 30 bytes, when in actuality the size ranges from 2 bytes to 30 bytes. RAWINPUT doesn’t pass the input unless there are 30 bytes received. (15 musical keys at once!)

To get around this issue, I’m writing an HID mini-driver (mini-port? semantics fail me at the moment) and I have a raw PDO created to help transfer the musical key data from the HID/Rawinput path to my own RawPDO communication path. I’m stuck at the point where I’m sending data from the KMDF driver to the User mode application. I use a DeviceIOControl() call and it comes back true with the number of bytes written that I tell it to. However, the buffer is full of 0x0s. and not the data that’s expected. An example of what is happening:

I press a key on the keyboard, it sends 0x03|0x7F|0x56. I watch the KMDF procedures (via WinDBG) from the notification that there is data from the continuous reader to when the rawPDO pops my IOCTL from the rawPDO’s queue, get the output buffer, take the data and assign 0x03|etc to the user buffer. I ‘receieve’ the data in my Windows Application and it shows 0x0|0x0|0x0.

I’m stuck, so I figured I’d ask the KMDF gurus for some help. I suspect it’s the way I’m allocating my buffers or something of the sort.

Here’s the code from the KMDF code and the application:

KMDF:

VOID
MusicKBDFilter_Send_MIDI_Data(

IN PDEVICE_EXTENSION devContext, // Device Context
IN BYTE MIDI_DATA, // Actual MIDI Data
IN size_t BufferLength //Number of Bytes

)
{
WDFREQUEST irRequest;
NTSTATUS status = STATUS_SUCCESS;
PRPDO_DEVICE_DATA myPdoData = NULL;
BYTE outMIDI_DATA[30]={0};
size_t bytesReturned=0;
size_t i;

myPdoData = PdoGetData(devContext->PdoDevice);

status = WdfIoQueueRetrieveNextRequest(myPdoData->MIDI_Queue, &irRequest);
if(NT_SUCCESS(status))
{
status = WdfRequestRetrieveUnsafeUserOutputBuffer(
irRequest,
BufferLength,
(PVOID *)outMIDI_DATA,
&bytesReturned);// BufferLength

for (i=0;i {
outMIDI_DATA[i]=MIDI_DATA[i];
}

if(NT_SUCCESS(status))
{
WdfRequestCompleteWithInformation(irRequest, STATUS_SUCCESS, bytesReturned);
}
}

return;

}

The Application Code: (not all code, but the essentials)

BYTE reportBuffer[0x20] = {0};
reportBuffer[0]=0x3;
result = DeviceIoControl(m_hDev, IOCTL_CTPKFILTER_GET_MIDI_DATA, NULL,0,reportBuffer, 0x20,&dwBytesRead,NULL);

And that returns 0x3|0x0|0x0|etc.

Thanks!


NTDEV is sponsored by OSR

OSR is HIRING!! See http://www.osr.com/careers

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</mailto:xxxxx></mailto:xxxxx>

Hi,

So, I didn?t completely explain everything the first time. (big
surprise).

I actually used METHOD_BUFFERED with the same results before
sending the code in. After switching to neither (must?ve misread the WDF book),
I sent in the request for help.

They keyboard is a Multi_Interface device. The QWERTY keyboard
is MI_00 and Musical Keys is under MI_ 01 with 2 other 3 collections. The Music
Keyboard is under the third collection with its usage page reported as ?0xFF00?
and Page 0x1. The other two collections are 0xc and 0x80. So, there are HID
devices in this device as well.

The end goal is to make it be a MIDI device, but at the same
time, I?m also treating it as my own ?Toaster? device. When I was researching
adding a MIDI device, I read that audio devices are still done via WDM.

But, if I understand you correctly, I?m going about it the wrong
way?

Thanks!

–Will Jones

From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Sunday, May 05, 2013 1:52 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Losing Data During ‘successful’ DeviceIOControl

Is the music keyboard keys reported through the (typing) keyboard? It should
really be a USB audio device and report itself as a midi endpoint. Or at least
its own top level collection. Also, do not use method_neither, use
METHOD_BUFFERED.

d

Bent from my phone


From: xxxxx@huskers.unl.edu
Sent: ?5/?5/?2013 11:21 AM
To: Windows System Software Devs Interest List mailto:xxxxx
Subject: [ntdev] Losing Data During ‘successful’ DeviceIOControl

Hello,

I’m a beginner when it comes to driver programming, so pardon what may be a
stupid question.

I’m writing an HID mini-driver (mini-port?) for a keyboard that has both a
qwerty keyboard as well as a musical keyboard.

Currently, I can’t use RAWINPUT because the Music Keyboard report descriptor
states that the the report size is 30 bytes, when in actuality the size ranges
from 2 bytes to 30 bytes. RAWINPUT doesn’t pass the input unless there are 30
bytes received. (15 musical keys at once!)

To get around this issue, I’m writing an HID mini-driver (mini-port? semantics
fail me at the moment) and I have a raw PDO created to help transfer the musical
key data from the HID/Rawinput path to my own RawPDO communication path. I’m
stuck at the point where I’m sending data from the KMDF driver to the User mode
application. I use a DeviceIOControl() call and it comes back true with the
number of bytes written that I tell it to. However, the buffer is full of 0x0s.
and not the data that’s expected. An example of what is happening:

I press a key on the keyboard, it sends 0x03|0x7F|0x56. I watch the KMDF
procedures (via WinDBG) from the notification that there is data from the
continuous reader to when the rawPDO pops my IOCTL from the rawPDO’s queue, get
the output buffer, take the data and assign 0x03|etc to the user buffer. I
‘receieve’ the data in my Windows Application and it shows 0x0|0x0|0x0.

I’m stuck, so I figured I’d ask the KMDF gurus for some help. I suspect it’s
the way I’m allocating my buffers or something of the sort.

Here’s the code from the KMDF code and the application:

KMDF:

VOID
MusicKBDFilter_Send_MIDI_Data(

IN PDEVICE_EXTENSION devContext, // Device Context
IN BYTE MIDI_DATA, // Actual MIDI Data
IN size_t BufferLength //Number of Bytes

)
{
WDFREQUEST irRequest;
NTSTATUS status = STATUS_SUCCESS;
PRPDO_DEVICE_DATA myPdoData = NULL;
BYTE outMIDI_DATA[30]={0};
size_t bytesReturned=0;
size_t i;

myPdoData = PdoGetData(devContext->PdoDevice);

status = WdfIoQueueRetrieveNextRequest(myPdoData->MIDI_Queue,
&irRequest);
if(NT_SUCCESS(status))
{
status = WdfRequestRetrieveUnsafeUserOutputBuffer(

irRequest,

BufferLength,
(PVOID *)outMIDI_DATA,
&bytesReturned);// BufferLength

for (i=0;i {
outMIDI_DATA[i]=MIDI_DATA[i];
}

if(NT_SUCCESS(status))
{
WdfRequestCompleteWithInformation(irRequest,
STATUS_SUCCESS, bytesReturned);
}
}

return;

}

The Application Code: (not all code, but the essentials)

BYTE reportBuffer[0x20] = {0};
reportBuffer[0]=0x3;
result = DeviceIoControl(m_hDev,
IOCTL_CTPKFILTER_GET_MIDI_DATA, NULL,0,reportBuffer, 0x20,&dwBytesRead,NULL);

And that returns 0x3|0x0|0x0|etc.

Thanks!


NTDEV is sponsored by OSR

OSR is HIRING!! See http://www.osr.com/careers

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

OSR is HIRING!! See http://www.osr.com/careers

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</mailto:xxxxx>

If all you want to do is read the hid device, you don’t need a km driver or filter at all. You can open the hid using createfile and read from it yourself . Raw input is an alternative, but you need a window. I have a hard time believing that raw input is flawed as you describe, perhaps you need to request all 30 bytes and then it will complete back with only the bytes reported (this is the normal way to read from a hid, you send a read for the max size it can report and then only what is reported is returned). I think you will be able to even report it as midi through a direct show filter, so no need for km there either.

d

Bent from my phone


From: William Jonesmailto:xxxxx
Sent: ?5/?5/?2013 12:21 PM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: RE: [ntdev] Losing Data During ‘successful’ DeviceIOControl

Hi,

So, I didn?t completely explain everything the first time. (big surprise).

I actually used METHOD_BUFFERED with the same results before sending the code in. After switching to neither (must?ve misread the WDF book), I sent in the request for help.

They keyboard is a Multi_Interface device. The QWERTY keyboard is MI_00 and Musical Keys is under MI_ 01 with 2 other 3 collections. The Music Keyboard is under the third collection with its usage page reported as ?0xFF00? and Page 0x1. The other two collections are 0xc and 0x80. So, there are HID devices in this device as well.

The end goal is to make it be a MIDI device, but at the same time, I?m also treating it as my own ?Toaster? device. When I was researching adding a MIDI device, I read that audio devices are still done via WDM.

But, if I understand you correctly, I?m going about it the wrong way?

Thanks!

–Will Jones

From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Sunday, May 05, 2013 1:52 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Losing Data During ‘successful’ DeviceIOControl

Is the music keyboard keys reported through the (typing) keyboard? It should really be a USB audio device and report itself as a midi endpoint. Or at least its own top level collection. Also, do not use method_neither, use METHOD_BUFFERED.

d

Bent from my phone
________________________________
From: xxxxx@huskers.unl.edumailto:xxxxx
Sent: ?5/?5/?2013 11:21 AM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: [ntdev] Losing Data During ‘successful’ DeviceIOControl
Hello,

I’m a beginner when it comes to driver programming, so pardon what may be a stupid question.

I’m writing an HID mini-driver (mini-port?) for a keyboard that has both a qwerty keyboard as well as a musical keyboard.

Currently, I can’t use RAWINPUT because the Music Keyboard report descriptor states that the the report size is 30 bytes, when in actuality the size ranges from 2 bytes to 30 bytes. RAWINPUT doesn’t pass the input unless there are 30 bytes received. (15 musical keys at once!)

To get around this issue, I’m writing an HID mini-driver (mini-port? semantics fail me at the moment) and I have a raw PDO created to help transfer the musical key data from the HID/Rawinput path to my own RawPDO communication path. I’m stuck at the point where I’m sending data from the KMDF driver to the User mode application. I use a DeviceIOControl() call and it comes back true with the number of bytes written that I tell it to. However, the buffer is full of 0x0s. and not the data that’s expected. An example of what is happening:

I press a key on the keyboard, it sends 0x03|0x7F|0x56. I watch the KMDF procedures (via WinDBG) from the notification that there is data from the continuous reader to when the rawPDO pops my IOCTL from the rawPDO’s queue, get the output buffer, take the data and assign 0x03|etc to the user buffer. I ‘receieve’ the data in my Windows Application and it shows 0x0|0x0|0x0.

I’m stuck, so I figured I’d ask the KMDF gurus for some help. I suspect it’s the way I’m allocating my buffers or something of the sort.

Here’s the code from the KMDF code and the application:

KMDF:

VOID
MusicKBDFilter_Send_MIDI_Data(

IN PDEVICE_EXTENSION devContext, // Device Context
IN BYTE MIDI_DATA, // Actual MIDI Data
IN size_t BufferLength //Number of Bytes

)
{
WDFREQUEST irRequest;
NTSTATUS status = STATUS_SUCCESS;
PRPDO_DEVICE_DATA myPdoData = NULL;
BYTE outMIDI_DATA[30]={0};
size_t bytesReturned=0;
size_t i;

myPdoData = PdoGetData(devContext->PdoDevice);

status = WdfIoQueueRetrieveNextRequest(myPdoData->MIDI_Queue, &irRequest);
if(NT_SUCCESS(status))
{
status = WdfRequestRetrieveUnsafeUserOutputBuffer(
irRequest,
BufferLength,
(PVOID *)outMIDI_DATA,
&bytesReturned);// BufferLength

for (i=0;i {
outMIDI_DATA[i]=MIDI_DATA[i];
}

if(NT_SUCCESS(status))
{
WdfRequestCompleteWithInformation(irRequest, STATUS_SUCCESS, bytesReturned);
}
}

return;

}

The Application Code: (not all code, but the essentials)

BYTE reportBuffer[0x20] = {0};
reportBuffer[0]=0x3;
result = DeviceIoControl(m_hDev, IOCTL_CTPKFILTER_GET_MIDI_DATA, NULL,0,reportBuffer, 0x20,&dwBytesRead,NULL);

And that returns 0x3|0x0|0x0|etc.

Thanks!


NTDEV is sponsored by OSR

OSR is HIRING!! See http://www.osr.com/careers

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

OSR is HIRING!! See http://www.osr.com/careers

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

OSR is HIRING!! See http://www.osr.com/careers

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</mailto:xxxxx></mailto:xxxxx></mailto:xxxxx></mailto:xxxxx>

I was hoping you wouldn’t take the comment as ‘rawinput is flawed’, it’s just not compatable. As far as I’m concerned, it’s reading the descriptor, and follows what the descriptor says. Honestly, the only way I got RAWINPUT to report an input from the musical keys was by pressing 15 keys at once (2 bytes per key), and then I received a report from Rawinput. Annoying? Yes. Flawed? No. Much like the military, you have to have all 30 of these things to be let in. Annoying? Yes. Flawed? No. (Debatable, but I hope you see my point).

Also, I tried reading via ReadFile but it didn’t work. But considering it was the first thing I tried, and I didn’t understand much yet, I probably got something wrong. So I should try it again.

Also, just checked the ReadFile with the same results. Have to press 15 keys to get it to report anything. If I report that I want 3 bytes, i get the “INVALID_USER_BUFFER”. But, when I make it the size of the report (0x1F), the readfile read’s in the full 30 bytes without any error. It was at this point I started to write my own driver.

Hidclass doesn’t buffer up partial reports, so I think that only getting 15 reports at a time is something the hardware is doing. If that is true, doesn’t matter if you write a driver or not.

What specific type of driver are you writing? What hardware id are you matching against in the inf

d

Bent from my phone


From: xxxxx@huskers.unl.edumailto:xxxxx
Sent: ?5/?5/?2013 2:09 PM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: RE:[ntdev] Losing Data During ‘successful’ DeviceIOControl

Also, just checked the ReadFile with the same results. Have to press 15 keys to get it to report anything. If I report that I want 3 bytes, i get the “INVALID_USER_BUFFER”. But, when I make it the size of the report (0x1F), the readfile read’s in the full 30 bytes without any error. It was at this point I started to write my own driver.


NTDEV is sponsored by OSR

OSR is HIRING!! See http://www.osr.com/careers

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</mailto:xxxxx></mailto:xxxxx>

Hmm, I’m still not being clear. Sorry about that.

It’s not sending 15 reports, it’s sending 1 report with information on 15 keys.

It’s report is structured like this:

ID | KEY1ON/OFF_NOTE | KEY1_VELOCITY | KEY2ON/OFF_NOTE | KEY2ON/OFF_VELOCITY | etc…

each ‘|’ represents a byte.

So, if I press 1 key, the device will send a 3 byte report (including ID). if I press 15 keys, the device will send a 31 byte report (Including ID).

USB\VID_041E&PID_2801&MI_01 is the Harware ID.
Creative Labs ProdiKeys USB.

I’m a Computer Engineer (B.S. 2004 USAFA) and a Music composition student (M.M. UNL 2014 [expected]) and I’d like to be able use this thing so I can have a keyboard on my desk without eating a lot of room. It’s been unsupported since Vista, so I figured I’d write my own driver.

I also wanted to learn how to write drivers for Windows, and figure this would be a great learning experience.

My point is that is sounds like the keyboard always sends a report only when it has info on 15 keys. Hidclass doesn’t buffer and way for all 15 keys, it just pushes up each report from the device (perhaps stripping off the report id).

Are you replacing hidusb in the stack? Or filtering below it? When you see an urb read complete back up from the device, does it contain info on just the keys immediately pressed or always info on 15 keys?

d

Bent from my phone


From: xxxxx@huskers.unl.edumailto:xxxxx
Sent: ?5/?5/?2013 3:33 PM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: RE:[ntdev] Losing Data During ‘successful’ DeviceIOControl

Hmm, I’m still not being clear. Sorry about that.

It’s not sending 15 reports, it’s sending 1 report with information on 15 keys.

It’s report is structured like this:

ID | KEY1ON/OFF_NOTE | KEY1_VELOCITY | KEY2ON/OFF_NOTE | KEY2ON/OFF_VELOCITY | etc…

each ‘|’ represents a byte.

So, if I press 1 key, the device will send a 3 byte report (including ID). if I press 15 keys, the device will send a 31 byte report (Including ID).

USB\VID_041E&PID_2801&MI_01 is the Harware ID.
Creative Labs ProdiKeys USB.

I’m a Computer Engineer (B.S. 2004 USAFA) and a Music composition student (M.M. UNL 2014 [expected]) and I’d like to be able use this thing so I can have a keyboard on my desk without eating a lot of room. It’s been unsupported since Vista, so I figured I’d write my own driver.


NTDEV is sponsored by OSR

OSR is HIRING!! See http://www.osr.com/careers

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</mailto:xxxxx></mailto:xxxxx>

Looking more closely at your code, I you are passing an array of bytes when retrieving the output pointer. Assuming method buffered, you want to pass a pointer a pointer to get the output buffer, so something like this

BYTE* outMIDI_DATA;
size_t bytesReturned=0;

WdfRequestRetrieveOuputBuffer(irRequest, , &outMIDI_DATA, &bytesReturned);

RtlCopyMemory(outMIDI_DATA, MIDI_DATA, );

Btw, having a global MIDI_DATA is pretty bad form, it should be stored in the device context

d

Bent from my phone

From: Doron Holanmailto:xxxxx
Sent: ?5/?5/?2013 11:51 AM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: RE: [ntdev] Losing Data During ‘successful’ DeviceIOControl

Is the music keyboard keys reported through the (typing) keyboard? It should really be a USB audio device and report itself as a midi endpoint. Or at least its own top level collection. Also, do not use method_neither, use METHOD_BUFFERED.

d

Bent from my phone

From: xxxxx@huskers.unl.edumailto:xxxxx
Sent: ?5/?5/?2013 11:21 AM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: [ntdev] Losing Data During ‘successful’ DeviceIOControl

Hello,

I’m a beginner when it comes to driver programming, so pardon what may be a stupid question.

I’m writing an HID mini-driver (mini-port?) for a keyboard that has both a qwerty keyboard as well as a musical keyboard.

Currently, I can’t use RAWINPUT because the Music Keyboard report descriptor states that the the report size is 30 bytes, when in actuality the size ranges from 2 bytes to 30 bytes. RAWINPUT doesn’t pass the input unless there are 30 bytes received. (15 musical keys at once!)

To get around this issue, I’m writing an HID mini-driver (mini-port? semantics fail me at the moment) and I have a raw PDO created to help transfer the musical key data from the HID/Rawinput path to my own RawPDO communication path. I’m stuck at the point where I’m sending data from the KMDF driver to the User mode application. I use a DeviceIOControl() call and it comes back true with the number of bytes written that I tell it to. However, the buffer is full of 0x0s. and not the data that’s expected. An example of what is happening:

I press a key on the keyboard, it sends 0x03|0x7F|0x56. I watch the KMDF procedures (via WinDBG) from the notification that there is data from the continuous reader to when the rawPDO pops my IOCTL from the rawPDO’s queue, get the output buffer, take the data and assign 0x03|etc to the user buffer. I ‘receieve’ the data in my Windows Application and it shows 0x0|0x0|0x0.

I’m stuck, so I figured I’d ask the KMDF gurus for some help. I suspect it’s the way I’m allocating my buffers or something of the sort.

Here’s the code from the KMDF code and the application:

KMDF:

VOID
MusicKBDFilter_Send_MIDI_Data(

IN PDEVICE_EXTENSION devContext, // Device Context
IN BYTE MIDI_DATA, // Actual MIDI Data
IN size_t BufferLength //Number of Bytes

)
{
WDFREQUEST irRequest;
NTSTATUS status = STATUS_SUCCESS;
PRPDO_DEVICE_DATA myPdoData = NULL;
BYTE outMIDI_DATA[30]={0};
size_t bytesReturned=0;
size_t i;

myPdoData = PdoGetData(devContext->PdoDevice);

status = WdfIoQueueRetrieveNextRequest(myPdoData->MIDI_Queue, &irRequest);
if(NT_SUCCESS(status))
{
status = WdfRequestRetrieveUnsafeUserOutputBuffer(
irRequest,
BufferLength,
(PVOID *)outMIDI_DATA,
&bytesReturned);// BufferLength

for (i=0;i {
outMIDI_DATA[i]=MIDI_DATA[i];
}

if(NT_SUCCESS(status))
{
WdfRequestCompleteWithInformation(irRequest, STATUS_SUCCESS, bytesReturned);
}
}

return;

}

The Application Code: (not all code, but the essentials)

BYTE reportBuffer[0x20] = {0};
reportBuffer[0]=0x3;
result = DeviceIoControl(m_hDev, IOCTL_CTPKFILTER_GET_MIDI_DATA, NULL,0,reportBuffer, 0x20,&dwBytesRead,NULL);

And that returns 0x3|0x0|0x0|etc.

Thanks!


NTDEV is sponsored by OSR

OSR is HIRING!! See http://www.osr.com/careers

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</mailto:xxxxx></mailto:xxxxx></mailto:xxxxx></mailto:xxxxx>

Ah, makes sense. Thanks!

And agreed that global MIDI_Data is bad form, some of the first things I’ll be fixing when I get the transfer working correctly.

–Will

Yes, however, I’m using a USB trace tool, and it shows when I press a key, that
it sends 0x03,0x7F,0x55. But Windows never says anything. This happens for
3-29 byte reports sent from the keyboard.

–Will Jones

From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Sunday, May 05, 2013 7:08 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Losing Data During ‘successful’ DeviceIOControl

My point is that is sounds like the keyboard always sends a report only when it
has info on 15 keys. Hidclass doesn’t buffer and way for all 15 keys, it just
pushes up each report from the device (perhaps stripping off the report id).

Are you replacing hidusb in the stack? Or filtering below it? When you see an
urb read complete back up from the device, does it contain info on just the keys
immediately pressed or always info on 15 keys?

d

Bent from my phone


Thanks again, that solved the problem!

Well the keyboard function is clearly behaving differently than the music keyboard function. Put a lower filter below hidusb on the music keyboard and see what length/type of data is being reported on each key press.

d

Bent from my phone


From: William Jonesmailto:xxxxx
Sent: ?5/?5/?2013 6:01 PM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: RE: [ntdev] Losing Data During ‘successful’ DeviceIOControl

Yes, however, I?m using a USB trace tool, and it shows when I press a key, that it sends 0x03,0x7F,0x55. But Windows never says anything. This happens for 3-29 byte reports sent from the keyboard.

–Will Jones

From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Sunday, May 05, 2013 7:08 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Losing Data During ‘successful’ DeviceIOControl

My point is that is sounds like the keyboard always sends a report only when it has info on 15 keys. Hidclass doesn’t buffer and way for all 15 keys, it just pushes up each report from the device (perhaps stripping off the report id).

Are you replacing hidusb in the stack? Or filtering below it? When you see an urb read complete back up from the device, does it contain info on just the keys immediately pressed or always info on 15 keys?

d

Bent from my phone
________________________________


NTDEV is sponsored by OSR

OSR is HIRING!! See http://www.osr.com/careers

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</mailto:xxxxx></mailto:xxxxx>

Well, i dunno if it’s late, or I’m just not skilled enough to come up with a lower filter that quick, or a little of both, but I’ll have to get back to you on this one.

xxxxx@huskers.unl.edu wrote:

It’s not sending 15 reports, it’s sending 1 report with information on 15 keys.
It’s report is structured like this:
ID | KEY1ON/OFF_NOTE | KEY1_VELOCITY | KEY2ON/OFF_NOTE | KEY2ON/OFF_VELOCITY | etc…
each ‘|’ represents a byte.

So, if I press 1 key, the device will send a 3 byte report (including ID). if I press 15 keys, the device will send a 31 byte report (Including ID).

The RIGHT way to handle this is to have your device follow the USB Audio
Class specification for MIDI devices. That way, you do not need a
driver at all. That’s what every USB MIDI keyboard in the world today does.

MIDI keyboards are critically dependent on low latency. I doubt you’ll
be able to achieve a coherent playing experience going through HID.


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

You’re right. However, my goal isn’t for a coherent playing experience. If I
wanted that, I’d buy a keyboard from M-Audio, etc. My goal is to learn KMDF,
UMDF, (a practical toaster if you will) and get a keyboard to work for single
note entry in Sibelius 7 / Notion 4.

Thanks!

–Will Jones

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Monday, May 06, 2013 2:43 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Losing Data During ‘successful’ DeviceIOControl

xxxxx@huskers.unl.edu wrote:

It’s not sending 15 reports, it’s sending 1 report with information on 15
keys.
It’s report is structured like this:
ID | KEY1ON/OFF_NOTE | KEY1_VELOCITY | KEY2ON/OFF_NOTE | KEY2ON/OFF_VELOCITY |
etc…
each ‘|’ represents a byte.

So, if I press 1 key, the device will send a 3 byte report (including ID). if
I press 15 keys, the device will send a 31 byte report (Including ID).

The RIGHT way to handle this is to have your device follow the USB Audio Class
specification for MIDI devices. That way, you do not need a driver at all.
That’s what every USB MIDI keyboard in the world today does.

MIDI keyboards are critically dependent on low latency. I doubt you’ll be able
to achieve a coherent playing experience going through HID.


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


NTDEV is sponsored by OSR

OSR is HIRING!! See http://www.osr.com/careers

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

William Jones wrote:

You’re right. However, my goal isn’t for a coherent playing experience. If I
wanted that, I’d buy a keyboard from M-Audio, etc. My goal is to learn KMDF,
UMDF, (a practical toaster if you will) and get a keyboard to work for single
note entry in Sibelius 7 / Notion 4.

How do you expect to do that plumbing? Sibelius expects to talk to a
MIDI driver. MIDI drivers in Windows are a subclass of audio drivers,
and audio drivers are complicated. How had you planned to route the
data from your HID layer into Sibelius?


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