Ejemplo n.º 1
0
        /// <summary>
        ///   Initialize an HidEvent from a WM_INPUT message
        /// </summary>
        /// <param name="hRawInputDevice">
        ///   Device Handle as provided by RAWINPUTHEADER.hDevice, typically accessed as
        ///   rawinput.header.hDevice
        /// </param>
        public HidEvent(Message aMessage, HidEventRepeatDelegate aRepeatDelegate)
        {
            RepeatCount = 0;
            IsValid     = false;
            IsKeyboard  = false;
            IsGeneric   = false;


            Time              = DateTime.Now;
            OriginalTime      = DateTime.Now;
            Timer             = new Timer();
            Timer.Elapsed    += (sender, e) => OnRepeatTimerElapsed(sender, e, this);
            Usages            = new List <ushort>();
            OnHidEventRepeat += aRepeatDelegate;

            if (aMessage.Msg != Const.WM_INPUT)
            {
                //Has to be a WM_INPUT message
                return;
            }

            if (Macro.GET_RAWINPUT_CODE_WPARAM(aMessage.WParam) == Const.RIM_INPUT)
            {
                IsForeground = true;
            }
            else if (Macro.GET_RAWINPUT_CODE_WPARAM(aMessage.WParam) == Const.RIM_INPUTSINK)
            {
                IsForeground = false;
            }

            //Declare some pointers
            var rawInputBuffer = IntPtr.Zero;
            //My understanding is that this is basically our HID descriptor
            var preParsedData = IntPtr.Zero;

            try
            {
                //Fetch raw input
                var rawInput = new RAWINPUT();
                if (!RawInput.GetRawInputData(aMessage.LParam, ref rawInput, ref rawInputBuffer))
                {
                    return;
                }

                //Fetch device info
                var deviceInfo = new RID_DEVICE_INFO();
                if (!RawInput.GetDeviceInfo(rawInput.header.hDevice, ref deviceInfo))
                {
                    return;
                }

                //Get various information about this HID device
                Device = new HidDevice(rawInput.header.hDevice);

                if (rawInput.header.dwType == Const.RIM_TYPEHID) //Check that our raw input is HID
                {
                    IsGeneric = true;

                    Debug.WriteLine("WM_INPUT source device is HID.");
                    //Get Usage Page and Usage
                    //Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage ID: 0x" + deviceInfo.hid.usUsage.ToString("X4"));
                    UsagePage       = deviceInfo.hid.usUsagePage;
                    UsageCollection = deviceInfo.hid.usUsage;

                    preParsedData = RawInput.GetPreParsedData(rawInput.header.hDevice);

                    if (
                        !(rawInput.hid.dwSizeHid > 1
                          //Make sure our HID msg size more than 1. In fact the first ushort is irrelevant to us for now
                          && rawInput.hid.dwCount > 0)) //Check that we have at least one HID msg
                    {
                        return;
                    }

                    //Allocate a buffer for one HID input
                    var hidInputReport = new byte[rawInput.hid.dwSizeHid];

                    Debug.WriteLine("Raw input contains " + rawInput.hid.dwCount + " HID input report(s)");

                    //For each HID input report in our raw input
                    for (var i = 0; i < rawInput.hid.dwCount; i++)
                    {
                        //Compute the address from which to copy our HID input
                        var hidInputOffset = 0;
                        unsafe
                        {
                            var source = (byte *)rawInputBuffer;
                            source        += sizeof(RAWINPUTHEADER) + sizeof(RAWHID) + (rawInput.hid.dwSizeHid * i);
                            hidInputOffset = (int)source;
                        }

                        //Copy HID input into our buffer
                        Marshal.Copy(new IntPtr(hidInputOffset), hidInputReport, 0, (int)rawInput.hid.dwSizeHid);

                        //Print HID input report in our debug output
                        var hidDump = "HID input report: ";
                        foreach (var b in hidInputReport)
                        {
                            hidDump += b.ToString("X2");
                        }
                        Debug.WriteLine(hidDump);

                        //Proper parsing now
                        uint usageCount = 1; //Assuming a single usage per input report. Is that correct?
                        var  usages     = new USAGE_AND_PAGE[usageCount];
                        var  status     = Function.HidP_GetUsagesEx(HIDP_REPORT_TYPE.HidP_Input, 0, usages, ref usageCount, preParsedData,
                                                                    hidInputReport, (uint)hidInputReport.Length);
                        if (status != HidStatus.HIDP_STATUS_SUCCESS)
                        {
                            Log.Error("HID: Could not parse HID data!");
                        }
                        else
                        {
                            //Debug.WriteLine("UsagePage: 0x" + usages[0].UsagePage.ToString("X4"));
                            //Debug.WriteLine("Usage: 0x" + usages[0].Usage.ToString("X4"));
                            //Add this usage to our list
                            Usages.Add(usages[0].Usage);
                        }
                    }
                }
                else if (rawInput.header.dwType == Const.RIM_TYPEMOUSE)
                {
                    IsMouse = true;

                    Debug.WriteLine("WM_INPUT source device is Mouse.");
                    // do mouse handling...
                }
                else if (rawInput.header.dwType == Const.RIM_TYPEKEYBOARD)
                {
                    IsKeyboard = true;

                    Debug.WriteLine("WM_INPUT source device is Keyboard.");
                    // do keyboard handling...
                    Debug.WriteLine("Type: " + deviceInfo.keyboard.dwType);
                    Debug.WriteLine("SubType: " + deviceInfo.keyboard.dwSubType);
                    Debug.WriteLine("Mode: " + deviceInfo.keyboard.dwKeyboardMode);
                    Debug.WriteLine("Number of function keys: " + deviceInfo.keyboard.dwNumberOfFunctionKeys);
                    Debug.WriteLine("Number of indicators: " + deviceInfo.keyboard.dwNumberOfIndicators);
                    Debug.WriteLine("Number of keys total: " + deviceInfo.keyboard.dwNumberOfKeysTotal);
                }
            }
            finally
            {
                //Always executed when leaving our try block
                Marshal.FreeHGlobal(rawInputBuffer);
                Marshal.FreeHGlobal(preParsedData);
            }

            //Start repeat timer if needed
            if (IsButtonDown)
            {
                StartRepeatTimer(iRepeatDelay);
            }

            IsValid = true;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Initialize an HidEvent from a WM_INPUT message
        /// </summary>
        /// <param name="aMessage"></param>
        /// <param name="aRepeatDelegate"></param>
        /// <param name="aRepeat"></param>
        /// <param name="aRepeatDelayInMs"></param>
        /// <param name="aRepeatSpeedInMs"></param>
        public Event(Message aMessage, HidEventRepeatDelegate aRepeatDelegate, bool aRepeat, int aRepeatDelayInMs = -1, int aRepeatSpeedInMs = -1)
        {
            RepeatCount = 0;
            IsValid     = false;
            IsKeyboard  = false;
            IsGeneric   = false;

            Time              = DateTime.Now;
            OriginalTime      = DateTime.Now;
            Timer             = new System.Timers.Timer();
            Timer.Elapsed    += (sender, e) => OnRepeatTimerElapsed(sender, e, this);
            Usages            = new List <ushort>();
            UsageValues       = new Dictionary <HIDP_VALUE_CAPS, uint>();
            OnHidEventRepeat += aRepeatDelegate;

            //Use custom repeat delay if specified
            if (aRepeatDelayInMs >= 0)
            {
                iRepeatDelayInMs = aRepeatDelayInMs;
            }

            //Use custom repeat speed if specified
            if (aRepeatSpeedInMs >= 0)
            {
                iRepeatSpeedInMs = aRepeatSpeedInMs;
            }

            //
            if (aMessage.Msg != Const.WM_INPUT)
            {
                //Has to be a WM_INPUT message
                return;
            }

            if (Macro.GET_RAWINPUT_CODE_WPARAM(aMessage.WParam) == Const.RIM_INPUT)
            {
                IsForeground = true;
            }
            else if (Macro.GET_RAWINPUT_CODE_WPARAM(aMessage.WParam) == Const.RIM_INPUTSINK)
            {
                IsForeground = false;
            }

            //Declare some pointers
            IntPtr rawInputBuffer = IntPtr.Zero;

            try
            {
                //Fetch raw input
                iRawInput = new RAWINPUT();
                if (!Win32.RawInput.GetRawInputData(aMessage.LParam, ref iRawInput, ref rawInputBuffer))
                {
                    Debug.WriteLine("GetRawInputData failed!");
                    return;
                }

                //Our device can actually be null.
                //This is notably happening for some keyboard events
                if (RawInput.header.hDevice != IntPtr.Zero)
                {
                    //Get various information about this HID device
                    Device = new Device(RawInput.header.hDevice);
                }

                if (RawInput.header.dwType == Win32.RawInputDeviceType.RIM_TYPEHID)  //Check that our raw input is HID
                {
                    IsGeneric = true;

                    Debug.WriteLine("WM_INPUT source device is HID.");
                    //Get Usage Page and Usage
                    //Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage ID: 0x" + deviceInfo.hid.usUsage.ToString("X4"));
                    UsagePage       = Device.Info.hid.usUsagePage;
                    UsageCollection = Device.Info.hid.usUsage;

                    if (!(RawInput.hid.dwSizeHid > 1 &&  //Make sure our HID msg size more than 1. In fact the first ushort is irrelevant to us for now
                          RawInput.hid.dwCount > 0))     //Check that we have at least one HID msg
                    {
                        return;
                    }

                    //Allocate a buffer for one HID input
                    InputReport = new byte[RawInput.hid.dwSizeHid];

                    Debug.WriteLine("Raw input contains " + RawInput.hid.dwCount + " HID input report(s)");

                    //For each HID input report in our raw input
                    for (int i = 0; i < RawInput.hid.dwCount; i++)
                    {
                        //Compute the address from which to copy our HID input
                        int hidInputOffset = 0;
                        unsafe
                        {
                            byte *source = (byte *)rawInputBuffer;
                            source        += sizeof(RAWINPUTHEADER) + sizeof(RAWHID) + (RawInput.hid.dwSizeHid * i);
                            hidInputOffset = (int)source;
                        }

                        //Copy HID input into our buffer
                        Marshal.Copy(new IntPtr(hidInputOffset), InputReport, 0, (int)RawInput.hid.dwSizeHid);
                        //
                        ProcessInputReport(InputReport);
                    }
                }
                else if (RawInput.header.dwType == RawInputDeviceType.RIM_TYPEMOUSE)
                {
                    IsMouse         = true;
                    UsagePage       = (ushort)Hid.UsagePage.GenericDesktopControls;
                    UsageCollection = (ushort)Hid.UsageCollection.GenericDesktop.Mouse;

                    Debug.WriteLine("WM_INPUT source device is Mouse.");
                    // do mouse handling...
                }
                else if (RawInput.header.dwType == RawInputDeviceType.RIM_TYPEKEYBOARD)
                {
                    IsKeyboard      = true;
                    UsagePage       = (ushort)Hid.UsagePage.GenericDesktopControls;
                    UsageCollection = (ushort)Hid.UsageCollection.GenericDesktop.Keyboard;

                    // Precise ALT key - work out if we are left or right ALT
                    if (iRawInput.keyboard.VKey == (ushort)Keys.Menu)
                    {
                        if (RawInput.keyboard.Flags.HasFlag(RawInputKeyFlags.RI_KEY_E0))
                        {
                            iRawInput.keyboard.VKey = (ushort)Keys.RMenu;
                        }
                        else
                        {
                            iRawInput.keyboard.VKey = (ushort)Keys.LMenu;
                        }
                    }

                    // Precise CTRL key - work out if we are left or right CTRL
                    if (iRawInput.keyboard.VKey == (ushort)Keys.ControlKey)
                    {
                        if (RawInput.keyboard.Flags.HasFlag(RawInputKeyFlags.RI_KEY_E0))
                        {
                            iRawInput.keyboard.VKey = (ushort)Keys.RControlKey;
                        }
                        else
                        {
                            iRawInput.keyboard.VKey = (ushort)Keys.LControlKey;
                        }
                    }

                    // Precise SHIFT key - work out if we are left or right SHIFT
                    if (iRawInput.keyboard.VKey == (ushort)Keys.ShiftKey)
                    {
                        if (RawInput.keyboard.MakeCode == 0x0036)
                        {
                            iRawInput.keyboard.VKey = (ushort)Keys.RShiftKey;
                        }
                        else
                        {
                            Debug.Assert(RawInput.keyboard.MakeCode == 0x002A);
                            iRawInput.keyboard.VKey = (ushort)Keys.LShiftKey;
                        }
                    }


                    Debug.WriteLine("WM_INPUT source device is Keyboard.");
                    // do keyboard handling...
                    if (Device != null)
                    {
                        Debug.WriteLine("Type: " + Device.Info.keyboard.dwType.ToString());
                        Debug.WriteLine("SubType: " + Device.Info.keyboard.dwSubType.ToString());
                        Debug.WriteLine("Mode: " + Device.Info.keyboard.dwKeyboardMode.ToString());
                        Debug.WriteLine("Number of function keys: " + Device.Info.keyboard.dwNumberOfFunctionKeys.ToString());
                        Debug.WriteLine("Number of indicators: " + Device.Info.keyboard.dwNumberOfIndicators.ToString());
                        Debug.WriteLine("Number of keys total: " + Device.Info.keyboard.dwNumberOfKeysTotal.ToString());
                    }
                }
            }
            finally
            {
                //Always executed when leaving our try block
                Marshal.FreeHGlobal(rawInputBuffer);
            }

            //We don't want to repeat every events. Key up events for instance must not be repeated.
            if (aRepeat &&                                            // If repeat is enabled
                IsGeneric &&                                          // Only generic HID event need repeat management, keyboards repeats are managed by the drivers
                (IsButtonDown ||                                      // and if we are dealing with a button down event
                 (GetDirectionPadState() != DirectionPadState.Rest))) //or our dpad is not at rest
            {
                StartRepeatTimer(iRepeatDelayInMs);
            }

            IsValid = true;
        }
Ejemplo n.º 3
0
    /// <summary>
    ///   Initialize an HidEvent from a WM_INPUT message
    /// </summary>
    /// <param name="hRawInputDevice">
    ///   Device Handle as provided by RAWINPUTHEADER.hDevice, typically accessed as
    ///   rawinput.header.hDevice
    /// </param>
    public HidEvent(Message aMessage, HidEventRepeatDelegate aRepeatDelegate)
    {
      RepeatCount = 0;
      IsValid = false;
      IsKeyboard = false;
      IsGeneric = false;


      Time = DateTime.Now;
      OriginalTime = DateTime.Now;
      Timer = new Timer();
      Timer.Elapsed += (sender, e) => OnRepeatTimerElapsed(sender, e, this);
      Usages = new List<ushort>();
      OnHidEventRepeat += aRepeatDelegate;

      if (aMessage.Msg != Const.WM_INPUT)
      {
        //Has to be a WM_INPUT message
        return;
      }

      if (Macro.GET_RAWINPUT_CODE_WPARAM(aMessage.WParam) == Const.RIM_INPUT)
      {
        IsForeground = true;
      }
      else if (Macro.GET_RAWINPUT_CODE_WPARAM(aMessage.WParam) == Const.RIM_INPUTSINK)
      {
        IsForeground = false;
      }

      //Declare some pointers
      var rawInputBuffer = IntPtr.Zero;
      //My understanding is that this is basically our HID descriptor 
      var preParsedData = IntPtr.Zero;

      try
      {
        //Fetch raw input
        var rawInput = new RAWINPUT();
        if (!RawInput.GetRawInputData(aMessage.LParam, ref rawInput, ref rawInputBuffer))
        {
          return;
        }

        //Fetch device info
        var deviceInfo = new RID_DEVICE_INFO();
        if (!RawInput.GetDeviceInfo(rawInput.header.hDevice, ref deviceInfo))
        {
          return;
        }

        //Get various information about this HID device
        Device = new HidDevice(rawInput.header.hDevice);

        if (rawInput.header.dwType == Const.RIM_TYPEHID) //Check that our raw input is HID                        
        {
          IsGeneric = true;

          Debug.WriteLine("WM_INPUT source device is HID.");
          //Get Usage Page and Usage
          //Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage ID: 0x" + deviceInfo.hid.usUsage.ToString("X4"));
          UsagePage = deviceInfo.hid.usUsagePage;
          UsageCollection = deviceInfo.hid.usUsage;

          preParsedData = RawInput.GetPreParsedData(rawInput.header.hDevice);

          if (
            !(rawInput.hid.dwSizeHid > 1
              //Make sure our HID msg size more than 1. In fact the first ushort is irrelevant to us for now
              && rawInput.hid.dwCount > 0)) //Check that we have at least one HID msg
          {
            return;
          }

          //Allocate a buffer for one HID input
          var hidInputReport = new byte[rawInput.hid.dwSizeHid];

          Debug.WriteLine("Raw input contains " + rawInput.hid.dwCount + " HID input report(s)");

          //For each HID input report in our raw input
          for (var i = 0; i < rawInput.hid.dwCount; i++)
          {
            //Compute the address from which to copy our HID input
            var hidInputOffset = 0;
            unsafe
            {
              var source = (byte*) rawInputBuffer;
              source += sizeof (RAWINPUTHEADER) + sizeof (RAWHID) + (rawInput.hid.dwSizeHid*i);
              hidInputOffset = (int) source;
            }

            //Copy HID input into our buffer
            Marshal.Copy(new IntPtr(hidInputOffset), hidInputReport, 0, (int) rawInput.hid.dwSizeHid);

            //Print HID input report in our debug output
            var hidDump = "HID input report: ";
            foreach (var b in hidInputReport)
            {
              hidDump += b.ToString("X2");
            }
            Debug.WriteLine(hidDump);

            //Proper parsing now
            uint usageCount = 1; //Assuming a single usage per input report. Is that correct?
            var usages = new USAGE_AND_PAGE[usageCount];
            var status = Function.HidP_GetUsagesEx(HIDP_REPORT_TYPE.HidP_Input, 0, usages, ref usageCount, preParsedData,
              hidInputReport, (uint) hidInputReport.Length);
            if (status != HidStatus.HIDP_STATUS_SUCCESS)
            {
              Log.Error("HID: Could not parse HID data!");
            }
            else
            {
              //Debug.WriteLine("UsagePage: 0x" + usages[0].UsagePage.ToString("X4"));
              //Debug.WriteLine("Usage: 0x" + usages[0].Usage.ToString("X4"));
              //Add this usage to our list
              Usages.Add(usages[0].Usage);
            }
          }
        }
        else if (rawInput.header.dwType == Const.RIM_TYPEMOUSE)
        {
          IsMouse = true;

          Debug.WriteLine("WM_INPUT source device is Mouse.");
          // do mouse handling...
        }
        else if (rawInput.header.dwType == Const.RIM_TYPEKEYBOARD)
        {
          IsKeyboard = true;

          Debug.WriteLine("WM_INPUT source device is Keyboard.");
          // do keyboard handling...
          Debug.WriteLine("Type: " + deviceInfo.keyboard.dwType);
          Debug.WriteLine("SubType: " + deviceInfo.keyboard.dwSubType);
          Debug.WriteLine("Mode: " + deviceInfo.keyboard.dwKeyboardMode);
          Debug.WriteLine("Number of function keys: " + deviceInfo.keyboard.dwNumberOfFunctionKeys);
          Debug.WriteLine("Number of indicators: " + deviceInfo.keyboard.dwNumberOfIndicators);
          Debug.WriteLine("Number of keys total: " + deviceInfo.keyboard.dwNumberOfKeysTotal);
        }
      }
      finally
      {
        //Always executed when leaving our try block
        Marshal.FreeHGlobal(rawInputBuffer);
        Marshal.FreeHGlobal(preParsedData);
      }

      //Start repeat timer if needed 
      if (IsButtonDown)
      {
        StartRepeatTimer(iRepeatDelay);
      }

      IsValid = true;
    }