Quantcast
Channel: Visual C forum
Viewing all articles
Browse latest Browse all 15302

Controlling NUM LOCK lamp on multiple keyboards.

$
0
0

I have a requirement to control, individually, the state of the NUM LOCK lamp on each of several USB keyboards connected to one PC (please don't ask why on earth I'd want to do such an odd thing - but it is a real requirement on a real project for my company).

I am using a code sequence comprising GetRawInputDeviceList(...) and GetRawInputDeviceInfo(...) to obtain the name (e.g. "\\?\HID#VID_413C&PID_2107# etc etc") of each of the USB Keyboard devices connected to the PC, and using that name in a CreateFile(...) call to get a handle to each device.

So far, so good. But, I am now trying to send the NUM LOCK key code to a particular keyboard using either DeviceIOControl(...) or WriteFile(...) and both calls are returning ERROR_INVALID_FUNCTION.

Clearly I am going wrong at this point - would anybody be able to help please? My detailed code is below...

int dwSize = sizeof( RAWINPUTDEVICELIST );
if ( GetRawInputDeviceList( NULL, &deviceCount, ( UINT )dwSize ) == 0 )
{
  PRAWINPUTDEVICELIST pRawInputDeviceList =
    ( PRAWINPUTDEVICELIST )malloc( dwSize * deviceCount );
  GetRawInputDeviceList( pRawInputDeviceList, &deviceCount, ( UINT )dwSize );

  // Iterate through the list, discarding undesired items
  // and retrieving further information on keyboard devices
  for ( UINT i = 0; i < deviceCount; i++ )
  {
    UINT pcbSize = 0;
    RAWINPUTDEVICELIST rid = *( pRawInputDeviceList + i );
    GetRawInputDeviceInfo( rid.hDevice, RIDI_DEVICENAME, NULL, &pcbSize );

    if ( pcbSize > 0 )
    {
      std::vector<TCHAR> data(pcbSize);
      LPTSTR pData = &data[0];
      GetRawInputDeviceInfo( rid.hDevice, RIDI_DEVICENAME, pData, &pcbSize );
      LPCTSTR lpctstrName = pData; // For CreateFile() later
      CString deviceName = ( char* )pData;

      // Drop the "root" keyboard and mouse devices used for Terminal 
      // Services and the Remote Desktop
      if ( deviceName.MakeUpper().Find( "ROOT" ) != -1 )
      {
        continue;
      }

      // If the device is identified in the list as a keyboard or HID
      // device, create a DeviceInfo object to store information about it
      if ( rid.dwType == RIM_TYPEKEYBOARD || rid.dwType == RIM_TYPEHID )
      {
        // Check with the Registry that this IS a Keyboard...
        // First, remove the common "\\?\" crap from the Device Name
        CString longDeviceName = deviceName;
        deviceName = deviceName.Right( deviceName.GetLength() - 4 );

        // Next, compile a Registry access string using the
		// three '#' divided bits (we ditch the class GUID)
        CString registryString = "SYSTEM\\CURRENTCONTROLSET\\ENUM\\";

        // 1) Class code
        int hash1 = deviceName.Find( '#' );
        if ( hash1 != -1 )
        {
          registryString += deviceName.Left( hash1 ) + "\\";

          // 2) SubClass code
          hash1++;
          int hash2 = deviceName.Find( '#', hash1 );
          if ( hash2 != -1 )
          {
            registryString += deviceName.Mid( hash1, hash2 - hash1 ) + "\\";

            // 3) Protocol code
            hash1 = hash2 + 1;
            hash2 = deviceName.Find( '#', hash1 );
            if ( hash2 != -1 )
            {
              registryString += deviceName.Mid( hash1, hash2 - hash1 );
            }
          }
        }

        // Get the device class from the registry
        HKEY Key;
        int result = RegOpenKeyEx( HKEY_LOCAL_MACHINE, registryString, 0, KEY_READ, &Key );
        char deviceClass[ 80 ] = {0};
        DWORD deviceClassLength = sizeof( deviceClass );
        result = RegQueryValueEx( Key, "Class", NULL, NULL,
		                          ( LPBYTE )deviceClass, &deviceClassLength );
        RegCloseKey( Key );

        // So, is it a keyboard?
        if ( _stricmp( deviceClass, "Keyboard" ) == 0 )
        {
          // Yes, get a handle to it...
          int lastErr = 0;
          HANDLE hFile = CreateFile( lpctstrName,
                        GENERIC_WRITE,
                        FILE_SHARE_READ | FILE_SHARE_WRITE,
                        NULL,
                        OPEN_EXISTING,
                        FILE_FLAG_OVERLAPPED, // FILE_ATTRIBUTE_NORMAL?
                        NULL );
          if ( hFile == INVALID_HANDLE_VALUE )
          {
            lastErr = GetLastError();
            lastErr = lastErr;
          }

          DWORD bytesReturned = 0;
          OVERLAPPED overlapStruct1 = {0};
          if ( !DeviceIoControl( hFile, 0x90, NULL, 0, NULL, 0, &bytesReturned, &overlapStruct1 ) )
          {
            lastErr = GetLastError();
            lastErr = lastErr;
          }

          char buf[1] = { 0x90 };
          DWORD bytesWritten = 0;
          OVERLAPPED overlapStruct2 = {0};
          if ( !WriteFile( hFile, buf, 1, &bytesWritten, &overlapStruct2 ) )
          {
            lastErr = GetLastError();
            lastErr = lastErr;
          }
        }
      }
    }
  }
}


Regards, Pennant Mike.


Viewing all articles
Browse latest Browse all 15302

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>