Sign in to follow this  
Erius

Very odd buffered raw input reading problem

Recommended Posts

Greetings. :) As the title suggests, I'm having a very odd issue with doing buffered reads of raw input. This is my first time using the raw input API, so maybe I'm doing something wrong and thus calling M$ silly is uncalled for, but I'm seriously starting to doubt myself. Anyway. Time for some code, pretty much 1:1 MSDN stuff.
 UINT cbSize; 

   GetRawInputBuffer(NULL, &cbSize, sizeof(RAWINPUTHEADER));
    cbSize *= 16;            /* this is a wild guess <- comment by the author of the documentation code, it's making me wonder what SHOULD be there...*/

    PRAWINPUT pRawInput = (PRAWINPUT)malloc(cbSize); 
    if (pRawInput == NULL) 
    {
        return; 
    } 
    for (;;) 
    {
        UINT cbSizeT = cbSize;
        UINT nInput = GetRawInputBuffer(pRawInput,&cbSizeT,sizeof(RAWINPUTHEADER)); //<- this is the problem child
   
        if (nInput == 0) 
        {
            break;
        }
        assert(nInput != -1);
        PRAWINPUT* paRawInput = (PRAWINPUT*)malloc(sizeof(PRAWINPUT) * 
                                 nInput);
        if (paRawInput == NULL) 
        {

            break; 
        } 
        PRAWINPUT pri = pRawInput;
        for (UINT i = 0; i < nInput; ++i) 
        { 
  
            paRawInput[i] = pri;
            pri = NEXTRAWINPUTBLOCK(pri);
        }
        // to clean the buffer
        DefRawInputProc(paRawInput, nInput, sizeof(RAWINPUTHEADER)); 
        
        free(paRawInput);
    }
    free(pRawInput);




Well, that's it. Ever since today, the problem child behaves very badly and throws "0x0000007A, The data area passed to a system call is too small. " Varuables have the following values at the breaking point: - cbSizeT is 40 - cbSize is 0 - pRawInput's header is all messed up - nInput is -1 or 0xFFFFFFFF Edit: I guess it throws that error because when it happens, it get passed "0" as cbsize has that value, but that somehow doesn't help me, much... The assertion triggers very oddly, sometimes immedetialy after moving the mouse, or hitting a key,sometimes it's a bit delayed. My mind is boggled. It worked flawlessly yesterday. The devices seem to register correctly. So yeah, I am stumped. Resources about raw input are veryrare it seems, and the documentation is really concise. I feel helpless, so any pointers would be great! Also, on an unrelated note: My computer produces a feint beeping sound whenever a conditional breakpoint is evaluated but not triggered. The frequency of that beep changes depending on where I put the breakpoint. I find that very odd, I'm using MS VisualStudio 2k8 if that would be a clue. MAybe it's like that beep in CRT monitors, but while that would give the unknown enemy a face, it would still worry me. Heh. Anyway, thanks in advance!

Share this post


Link to post
Share on other sites
Sorry for double posting, not intended as a bump, since at this point it's still the upmost thread, but to tell you that this routine is called on every frame in the main loop, even before the message pump.

This seems to be the only way, without multithreading, to actually get all the input, while waiting for a WM_INPUT message seems to only give the input after WM_INPUT got triggered.

Maybe that is the reason it screws up, maybe this is a wrong assumption and I have to stick it into a conditional function, and not one that enters on each frame.

Edit:
Put in a break on the event when it happens.
Does that make me miss out on events? It does happen when I give input, after all.
Mouse ones more frequently than keyboard ones.

[Edited by - Erius on November 10, 2009 10:56:12 PM]

Share this post


Link to post
Share on other sites
Is there any reason you're doing buffered input? Doing a standard read works great for me. Here's an exact snippet of the handler I use in my code
		case WM_INPUT: {
static std::vector<BYTE> rawInputData;
UINT dwSize;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
rawInputData.resize(dwSize);
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &rawInputData[0], &dwSize, sizeof(RAWINPUTHEADER)) == dwSize) {
RAWINPUT* raw = (RAWINPUT*)&rawInputData[0];
if (raw->header.dwType == RIM_TYPEMOUSE)
rawMouse(raw->data.mouse.lLastX, raw->data.mouse.lLastY);
}
return 0;
}

As you can see it's far easier and I don't have any problems with it. "rawMouse" is my own handler function.

Share this post


Link to post
Share on other sites
Well, I want to implement it because I assume that a buffered read can deliver simultaneus input events, giving each frame all the input that has happened.

I have to agree that a standard read might be better though, seeing how the input is supposed to go to a handler anyway, because I like good controls, and not everyone presses buttons perfectly simultaneus, so there will have to be a very short delay system to make that easier.


I know that it's more important to get things running at first, instead of focusing on optimisation, but I really love good controls, and buffered read MUST have some merit.

If the buffered version drives me too close to the edge though, I will ditch it, of course, but it must have SOME use.

Still, maybe I see the use wrongly, I'm a rookie at realtime programming, after all, but in this case, if I get slightly less precise controls for going the easier way, then I rather stick to the hard one.

It's justI lack resources and low level knowledge about this thing, so all I have is reasoning, and buffered input just seems more precise and complete.

The high framerate might make that edge(if it does have an edge over standard read) irrelevant, but if I am the only judge to ask...yeah...

Thank you for your input though. =)

Share this post


Link to post
Share on other sites
I can certainly appreciate the notion that there must be some benefit to it. I'm not sure myself that it would be a speed benefit, though I imagine it could be an accuracy benefit. In my mind something that is buffered means that something between the producer and the consumer of the data is accumulating/delaying samples. It may be that buffering is what gives you every single sample whereas the standard read gives you all of the ones since the last read combined together. Or it could be that unbuffered input means that samples can be lost.

I could easily be completely wrong of course. Regardless, I hope that between your code and mine and whatever else you can find, you get something that works well for your situation.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this