예제 #1
0
        /// <summary>
        /// Get all our usages, those are typically the buttons currently pushed on a gamepad.
        /// For a remote control it's usually just the one button that was pushed.
        /// </summary>
        private void GetUsages(byte[] inputReport)
        {
            /// Do proper parsing of our HID report
            /// First query our usage count
            uint usageCount = 0;

            USAGE_AND_PAGE[] usages = null;
            HidStatus        status = Win32.Win32Hid.NativeMethods.HidP_GetUsagesEx(HIDP_REPORT_TYPE.HidP_Input, 0, usages, ref usageCount, this.Device.PreParsedData, inputReport, (uint)inputReport.Length);

            if (status == HidStatus.HIDP_STATUS_BUFFER_TOO_SMALL)
            {
                // Allocate a large enough buffer
                usages = new USAGE_AND_PAGE[usageCount];

                // ...and fetch our usages
                status = Win32.Win32Hid.NativeMethods.HidP_GetUsagesEx(HIDP_REPORT_TYPE.HidP_Input, 0, usages, ref usageCount, this.Device.PreParsedData, inputReport, (uint)inputReport.Length);
                if (status != HidStatus.HIDP_STATUS_SUCCESS)
                {
                    Debug.WriteLine("Second pass could not parse HID data: " + status.ToString());
                }
            }
            else if (status != HidStatus.HIDP_STATUS_SUCCESS)
            {
                Debug.WriteLine("First pass could not parse HID data: " + status.ToString());
            }

            Debug.WriteLine("Usage count: " + usageCount.ToString());

            // Copy usages into this event
            if (usages != null)
            {
                foreach (var bc in this.Device.InputButtonCapabilities)
                {
                    var b = false;
                    foreach (USAGE_AND_PAGE up in usages)
                    {
                        if (up.UsagePage == bc.UsagePage && up.Usage == bc.NotRange.Usage)
                        {
                            b = true;
                            break;
                        }
                    }
                    this.Buttons[bc] = b;
                }
            }
            else
            {
                foreach (var bc in this.Device.InputButtonCapabilities)
                {
                    this.Buttons[bc] = false;
                }
            }
        }
예제 #2
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;
        }