How to detect only attached device using win32 GetRawInputDeviceList?

Started by
6 comments, last by Giallanon 10 years, 4 months ago

I'm using GetRawInputDeviceList() to obtain a list of input devices, and it's working fine, but it returns something like 3 o 4 keyboards and 2 or 3 mouses even if I only have 1 keyboard and 1 mouse attached.

I guess that what the function is returning is a list of all devices ever seen by the OS.

I can't find a way to know if a device is actually attached (and working) or it's a ghost.

I remember that with direct input there was a flag to set in order to retreive only attached devices, so I'm guessing that there should be something similar to use with RawInput family of functions, but so far I've found any.

Any idea?

Advertisement

http://stackoverflow.com/questions/6881114/too-many-raw-input-device-from-getrawinputdevicelist#

(I hope it's ok to post stackoverflow links here - I haven't seen anyone else doing it, but stackoverflow usually has a lot of good answers...)

I was aware of this answer on stackoverflow, but it's not very useful because it doesn't clarify anything and doesn't even help the OP to understand which one of the 3 keyboards is the one attached, which it's the same problem I'm facing

Really, because it's pretty clear to me, but I'll try to explain anyway:

You have to use GetRawInputDeviceInfo for each of the devices returned by GetRawInputDeviceList to get more info about the devices, but you're already doing this, since you mentioned you're only looking at the keyboard devices.

Next, from what I understand of that stackoverflow response:

1) The first keyboard device returned by GetRawInputDeviceList (in the order in which GetRawInputDeviceList returns them), is a sort of virtual keyboard created by the system, which handles keyboard events from all physical attached keyboards.

2) The second keyboard device is a physical keyboard - if there's only one keyobard attached, then this is it.

3) The third keyboard device is also physical

4) So on...

If that is true, then IMO, you should either use the first device (the virtual one) if your game requires only one keyboard, the second one if you want the "main" keyboard", or offer a choice between all of them. Unfortunately, I cannot find this info anywhere on MSDN, to verify if it's correct, but like I said, I tend to trust stackoverflow most of the time.

As for why you're seeing three (or four?) keyboards when you say you only have one: could the extra ones (after the first two) be Bluetooth devices? You can verify in Device Manager.


...clarify anything and doesn't even help the OP...

Aren;t you the OP? :)

Well the answer on stackoverflow seems based on guesses and not on official documentation. If the program I'm working on was for personal use, I could make a guess and live with it, but who can assure me that the same assumptions will hold on every pc with every possible combinations of mouse keyboard and whatever else?

There should be an api to use to understand if a device is alive or not...

From a MVP page (don't ask me which one) I took this to weed out those "virtual" combined devices like this:

  UINT        numDevices = 0;
  if ( GetRawInputDeviceList( NULL, &numDevices, sizeof( RAWINPUTDEVICELIST ) ) != 0 )
  {
    // Error?
    return false;
  }
  RAWINPUTDEVICELIST*   pDeviceData = new RAWINPUTDEVICELIST[numDevices];
  if ( GetRawInputDeviceList( pDeviceData, &numDevices, sizeof( RAWINPUTDEVICELIST ) ) == -1 )
  {
    // Error
    delete[] pDeviceData;
    return false;
  }
  int numTotalControls    = 0;
  int numTotalVirtualKeys = 0;
  int currentHIDJoystickOrGamepad = 0;
  for ( UINT i = 0; i < numDevices; ++i )
  {
    wchar_t             pathBuffer[260 + 4];
    UINT                bufferSize = UINT( sizeof( pathBuffer ) / sizeof( pathBuffer[0] ) );
    std::wstring        name;
 
    bufferSize = GetRawInputDeviceInfoW( pDeviceData[i].hDevice, RIDI_DEVICENAME, pathBuffer, &bufferSize );
    if ( sizeof pathBuffer / sizeof pathBuffer[0] < bufferSize )
    {
      // Negative UINTs werden sehr groß positiv
      dh::Log( "invalid HID (%d, %x): could not retrieve its path", i, pDeviceData[i].hDevice );
      continue;
    }
    std::wstring    originalName = pathBuffer;
    pathBuffer[1] = L'\\';
    HANDLE              ntHandle = CreateFileW( pathBuffer,
                                                0u,
                                                FILE_SHARE_READ | FILE_SHARE_WRITE, // wir können anderen Prozessen nicht verbieten, das HID zu benutzen
                                                NULL,
                                                OPEN_EXISTING,
                                                0u,
                                                NULL );
    if ( INVALID_HANDLE_VALUE == ntHandle )
    {
      dh::Log( "%d: invalid HID: could not open its handle", i );
      continue;
    }
    if ( GR::Strings::ToUpper( pathBuffer ).find( L"ROOT" ) != std::string::npos )
    {
      // skip combined devices, we only want real devices
      //dh::Log( "skip combined device %d (%x)", i, pDeviceData[i].hDevice );
      continue;
    }
    // snip ... from here one gather additional data from devices

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

That will work to get rid of the virtual devices, but it won't get rid of disconnected devices.

Is CreateFile supposed to return INVALID_HANDLE_VALUE for disconnected devices? Because it's not working that way for me. For a Bluetooth keyboard (it's actually a keyboard app on my phone). When I shutdown the app, the phone's bluetooth goes off, but the keyboard still shows in Device Manager. It only goes away after a few minutes, but I assume in this case, my application will receive a WM_INPUT_DEVICE_CHANGE message if I register for them.

Also, PS/2 does not have plug and play capability, so if you remove a PS/2 mouse or keyboard, it will probably not be detected by Windows. But if you do this, then do not plug the keyboard or mouse back in while the computer is still running - you might ruin the PS/2 controller; you have to shutdown the computer, then plug in the keyboard /mouse.

CreateFile!!! How I didn't thought of it before...it seems pretty obvious now.

Thank you Endurion, I think this will work for me.

As for disconnected devices, it's not a problem for me now, because I can assume that any devices I found at startup will last for the entire duration of the program.

This topic is closed to new replies.

Advertisement