Ejemplo n.º 1
0
        public bool StartListenInput(HidDevice[] devices)
        {
            var rids = devices.Select(x => new RAWINPUTDEVICE
            {
                usUsagePage = x.UsagePage,
                usUsage     = x.Usage,
                dwFlags     = RIDEV.INPUTSINK,
                hwndTarget  = _handle
            }).ToArray();

            var structSize   = (uint)Marshal.SizeOf(typeof(RAWINPUTDEVICE));
            var isRegistered = RawInput.RegisterRawInputDevices(rids, (uint)rids.Length, structSize);
            var z            = WinKernel.GetLastError();

            return(isRegistered);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Retrieves the raw input header from the specified device.
        /// </summary>
        /// <remarks>See <see cref="GetRawInputData"/> for more information.</remarks>
        /// <param name="hRawInput">A handle to the <see cref="RAWINPUT"/> structure. This comes from the
        /// <b>lParam</b> in <see cref="WM.INPUT">WM_INPUT</see>.</param>
        /// <returns>The raw input header as <see cref="RAWINPUTHEADER"/>.</returns>
        public static RAWINPUTHEADER GetRawInputDataHeader(HRAWINPUT hRawInput)
        {
            uint size = RAWINPUTHEADER.SIZE;

            RAWINPUTHEADER ret = new RAWINPUTHEADER();

            ret.dwSize = size;

            uint err = GetRawInputDataH(hRawInput, RID.HEADER, ref ret, ref size, RAWINPUTHEADER.SIZE);

            if (err == uint.MaxValue)
            {
                throw new Exception(string.Format("Error getting header of WM_INPUT data. (Error code: 0x{0:X8})", WinKernel.GetLastError()));
            }

            return(ret);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Retrieves the raw input data from the specified device.
        /// </summary>
        /// <remarks>See <see cref="GetRawInputData"/> for more information.</remarks>
        /// <typeparam name="T">A <b>struct</b> that will be the type of the returned data.</typeparam>
        /// <param name="hRawInput">A handle to the <see cref="RAWINPUT"/> structure. This comes from the
        /// <b>lParam</b> in <see cref="WM.INPUT">WM_INPUT</see>.</param>
        /// <param name="size">Size of the <see cref="RAWINPUT"/> structure. Can be queried using
        /// <see cref="GetRawInputDataHeader"/>; the size is stored in <see cref="RAWINPUTHEADER.dwSize"/>.</param>
        /// <param name="offset">An offset to the start of the data, to be returned, in the resulting data of a
        /// <see cref="GetRawInputData"/> call, without the <see cref="RAWINPUTHEADER"/>, which is omitted anyway.</param>
        /// <returns>The raw input header as specified when called.</returns>
        public unsafe static T GetRawInputData <T>(HRAWINPUT hRawInput, int size, int offset = 0) where T : struct
        {
            if (size < (uint)Marshal.SizeOf(typeof(T)))
            {
                throw new ArgumentOutOfRangeException("size", "Must be greater than or equal to sizeof(RAWINPUT).");
            }

            IntPtr buffer = Marshal.AllocHGlobal(size);
            uint   dwSize = (uint)size;

            try
            {
                uint err = GetRawInputData(hRawInput, RID.INPUT, buffer, ref dwSize, RAWINPUTHEADER.SIZE);
                if (err == uint.MaxValue)
                {
                    throw new Exception(string.Format("Error getting WM_INPUT data. (Error code: 0x{0:X8})", WinKernel.GetLastError()));
                }

                return((T)Marshal.PtrToStructure(buffer + (int)RAWINPUTHEADER.SIZE + offset, typeof(T)));
            }
            finally
            {
                Marshal.FreeHGlobal(buffer);
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Returns a list of raw input device handles and raw input device types.
        /// </summary>
        /// <returns>The list of raw input device handles and raw input device types.</returns>
        public static List <Tuple <HANDLE, RIM_TYPE> > EnumerateDevices()
        {
            uint size = (uint)Marshal.SizeOf(typeof(RAWINPUTDEVICELIST));

            uint deviceCount = 0;

            uint err = GetRawInputDeviceList(null, ref deviceCount, size);

            if (err == uint.MaxValue)
            {
                throw new Exception(string.Format("Error enumerating raw input devices. (Error code: 0x{0:X8})", WinKernel.GetLastError()));
            }

            if (deviceCount == 0)
            {
                return(new List <Tuple <LRESULT, RIM_TYPE> >());
            }

            RAWINPUTDEVICELIST[] tmp = new RAWINPUTDEVICELIST[deviceCount + 16];         // Just a few more, for the case they just got attached.
            err = GetRawInputDeviceList(tmp, ref deviceCount, size);
            if (err == uint.MaxValue)
            {
                throw new Exception(string.Format("Error enumerating raw input devices. (Error code: 0x{0:X8})", WinKernel.GetLastError()));
            }

            List <Tuple <LRESULT, RIM_TYPE> > ret = new List <Tuple <LRESULT, RIM_TYPE> >();

            for (int i = 0; i < deviceCount; i++)
            {
                ret.Add(new Tuple <LRESULT, RIM_TYPE>(tmp[i].hDevice, tmp[i].dwType));
            }

            return(ret);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Retrieves the preparsed data of a raw input device.
        /// </summary>
        /// <param name="hDevice">A handle to the raw input device. This comes from the <b>lParam</b> of the
        /// <see cref="WM.INPUT">WM_INPUT</see> message, from the <see cref="RAWINPUTHEADER.hDevice">hDevice</see>
        /// member of <see cref="RAWINPUTHEADER"/>, or from <see cref="GetRawInputDeviceList"/>. It can also be
        /// <b>null</b> (IntPtr.Zero) if an application inserts input data, for example, by using <b>SendInput</b>.</param>
        /// <returns>The preparsed data of raw input device.</returns>
        public static byte[] GetRawInputDevicePreparsedData(HANDLE hDevice)
        {
            uint size = 0;
            uint err  = GetRawInputDeviceInfo(hDevice, RIDI.PREPARSEDDATA, IntPtr.Zero, ref size);

            if (err == uint.MaxValue)
            {
                throw new Exception(string.Format("Error determining preparsed data of device (length). (Error code: 0x{0:X8})", WinKernel.GetLastError()));
            }

            byte[] ret = new byte[size];

            err = GetRawInputDeviceInfo(hDevice, RIDI.PREPARSEDDATA, ret, ref size);
            if (err == uint.MaxValue)
            {
                throw new Exception(string.Format("Error determining preparsed data of device. (Error code: 0x{0:X8})", WinKernel.GetLastError()));
            }

            return(ret);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Retrieves information about the raw input device.
        /// </summary>
        /// <param name="hDevice">A handle to the raw input device. This comes from the <b>lParam</b> of the
        /// <see cref="WM.INPUT">WM_INPUT</see> message, from the <see cref="RAWINPUTHEADER.hDevice">hDevice</see>
        /// member of <see cref="RAWINPUTHEADER"/>, or from <see cref="GetRawInputDeviceList"/>. It can also be
        /// <b>null</b> (IntPtr.Zero) if an application inserts input data, for example, by using <b>SendInput</b>.</param>
        /// <returns>The information about the raw input device.</returns>
        public static RID_DEVICE_INFO GetRawInputDeviceInfo(HANDLE hDevice)
        {
            uint size = (uint)Marshal.SizeOf(typeof(RID_DEVICE_INFO));

            RID_DEVICE_INFO ret = new RID_DEVICE_INFO();

            ret.cbSize = size;

            uint err = GetRawInputDeviceInfo(hDevice, RIDI.DEVICEINFO, ref ret, ref size);

            if (err == uint.MaxValue)
            {
                throw new Exception(string.Format("Error determining device information. (Error code: 0x{0:X8})", WinKernel.GetLastError()));
            }

            return(ret);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Retrieves the device name of a raw input device.
        /// </summary>
        /// <param name="hDevice">A handle to the raw input device. This comes from the <b>lParam</b> of the
        /// <see cref="WM.INPUT">WM_INPUT</see> message, from the <see cref="RAWINPUTHEADER.hDevice">hDevice</see>
        /// member of <see cref="RAWINPUTHEADER"/>, or from <see cref="GetRawInputDeviceList"/>. It can also be
        /// <b>null</b> (IntPtr.Zero) if an application inserts input data, for example, by using <b>SendInput</b>.</param>
        /// <returns>The device name of the raw input device.</returns>
        public static string GetRawInputDeviceName(HANDLE hDevice)
        {
            uint size = 0;
            uint err  = GetRawInputDeviceInfo(hDevice, RIDI.DEVICENAME, IntPtr.Zero, ref size);

            if (err == uint.MaxValue)
            {
                throw new Exception(string.Format("Error determining device name (length). (Error code: 0x{0:X8})", WinKernel.GetLastError()));
            }

            size = Math.Max(err, size) + 1;

            StringBuilder tmp = new StringBuilder((int)size);

            err = GetRawInputDeviceInfo(hDevice, RIDI.DEVICENAME, tmp, ref size);
            if (err == uint.MaxValue)
            {
                throw new Exception(string.Format("Error determining device name. (Error code: 0x{0:X8})", WinKernel.GetLastError()));
            }

            return(tmp.ToString());
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Processes a <see cref="WM.INPUT">WM_INPUT</see> messages and raises the proper events.
        /// </summary>
        /// <param name="lParam">The handle to the raw input dataset.</param>
        /// <param name="size">The size, in bytes, of the raw input dataset.</param>
        public void ProcessInput(IntPtr lParam, uint size)
        {
            IntPtr buffer = Marshal.AllocHGlobal((int)size);
            uint   dwSize = size;

            try
            {
                uint err = RawInput.GetRawInputData(lParam, RID.INPUT, buffer, ref dwSize, RAWINPUTHEADER.SIZE);
                if (err == uint.MaxValue)
                {
                    throw new Exception(string.Format("Error getting WM_INPUT data. (Error code: 0x{0:X8})", WinKernel.GetLastError()));
                }

                RAWINPUTHEADER        inputHeader = (RAWINPUTHEADER)Marshal.PtrToStructure(buffer, typeof(RAWINPUTHEADER));
                SpaceMouseEventHeader eventHeader = (SpaceMouseEventHeader)Marshal.PtrToStructure(buffer + (int)RAWINPUTHEADER.SIZE, typeof(SpaceMouseEventHeader));

                int eventHeaderSize = SpaceMouseEventHeader.SIZE + (int)RAWINPUTHEADER.SIZE;

                switch (eventHeader.eventType)
                {
                case SpaceMouseEventType.Translation:
                    if (eventHeader.dwSizeHid == 7)                          // check report size for safety
                    {
                        EventHandler <SpaceMouseTranslationEventArgs> tEvt = Translation;
                        if (tEvt != null)                              // no need to handle if nobody is listing
                        {
                            for (int i = 0; i < eventHeader.dwCount; i++)
                            {
                                SpaceMouseTranslationEventData translation = (SpaceMouseTranslationEventData)Marshal.PtrToStructure(buffer + eventHeaderSize + i * (int)eventHeader.dwSizeHid, typeof(SpaceMouseTranslationEventData));
                                tEvt(this, new SpaceMouseTranslationEventArgs(inputHeader.hDevice, translation.X, translation.Y, translation.Z));
                            }
                        }
                    }
                    else if (eventHeader.dwSizeHid == 13)                          // "High Speed" firmware version includes both T and R vector in the same report
                    {
                        EventHandler <SpaceMouseTranslationEventArgs> tEvt = Translation;
                        EventHandler <SpaceMouseRotationEventArgs>    rEvt = Rotation;
                        if (tEvt != null || rEvt != null)                          // no need to handle if nobody is listing
                        {
                            for (int i = 0; i < eventHeader.dwCount; i++)
                            {
                                SpaceMouseTranslationRotationEventData transRot = (SpaceMouseTranslationRotationEventData)Marshal.PtrToStructure(buffer + eventHeaderSize + i * (int)eventHeader.dwSizeHid, typeof(SpaceMouseTranslationRotationEventData));
                                if (tEvt != null)
                                {
                                    tEvt(this, new SpaceMouseTranslationEventArgs(inputHeader.hDevice, transRot.X, transRot.Y, transRot.Z));
                                }
                                if (rEvt != null)
                                {
                                    rEvt(this, new SpaceMouseRotationEventArgs(inputHeader.hDevice, transRot.RX, transRot.RY, transRot.RZ));
                                }
                            }
                        }
                    }
                    break;

                case SpaceMouseEventType.Rotation:
                    if (eventHeader.dwSizeHid == 7)                          // check report size for safety
                    {
                        EventHandler <SpaceMouseRotationEventArgs> rEvt = Rotation;
                        if (rEvt != null)                              // no need to handle if nobody is listing
                        {
                            for (int i = 0; i < eventHeader.dwCount; i++)
                            {
                                SpaceMouseRotationEventData rotation = (SpaceMouseRotationEventData)Marshal.PtrToStructure(buffer + eventHeaderSize + i * (int)eventHeader.dwSizeHid, typeof(SpaceMouseRotationEventData));
                                rEvt(this, new SpaceMouseRotationEventArgs(inputHeader.hDevice, rotation.RX, rotation.RY, rotation.RZ));
                            }
                        }
                    }
                    break;

                case SpaceMouseEventType.Buttons:
                    if (eventHeader.dwSizeHid >= 5)                          // check report size for safety
                    {
                        EventHandler <SpaceMouseButtonsEventArgs> bEvt = Buttons;
                        if (bEvt != null)                              // no need to handle if nobody is listing
                        {
                            if (!DeviceToProduct.ContainsKey(inputHeader.hDevice))
                            {
                                var di = RawInput.GetRawInputDeviceInfo(inputHeader.hDevice);
                                DeviceToProduct.Add(inputHeader.hDevice, di.hid.dwProductId);
                            }

                            uint product = DeviceToProduct[inputHeader.hDevice];

                            for (int i = 0; i < eventHeader.dwCount; i++)
                            {
                                SpaceMouseButtonsEventData tmpButtons = (SpaceMouseButtonsEventData)Marshal.PtrToStructure(buffer + eventHeaderSize + i * (int)eventHeader.dwSizeHid, typeof(SpaceMouseButtonsEventData));

                                SpaceMouseButtons buttons = SpaceMouseButtons.NONE;
                                switch (product)
                                {
                                case ProductID.SpacePilot: buttons = FromSpacePilot(tmpButtons.ButtonState); break;

                                case ProductID.SpaceExplorer: buttons = FromSpaceExplorer(tmpButtons.ButtonState); break;

                                case ProductID.SpaceNavigator:
                                case ProductID.SpaceNavigatorforNotebooks:
                                case ProductID.SpaceMouse:
                                case ProductID.SpaceMouseWireless: buttons = FromSpaceMouse(tmpButtons.ButtonState); break;

                                case ProductID.SpacePilotPro: buttons = FromSpacePilotPro(tmpButtons.ButtonState); break;

                                case ProductID.SpaceMousePro:
                                case ProductID.SpaceMouseProWireless: buttons = FromSpaceMousePro(tmpButtons.ButtonState); break;

                                case ProductID.SpaceMouseTouch: buttons = FromSpaceMouseTouch(tmpButtons.ButtonState); break;
                                }

                                bEvt(this, new SpaceMouseButtonsEventArgs(inputHeader.hDevice, buttons));
                            }
                        }
                    }
                    break;
                }
            }
            finally
            {
                Marshal.FreeHGlobal(buffer);
            }
        }