/// <summary>
        /// Function to retrieve the capabilities of the xinput device.
        /// </summary>
        /// <param name="controller"></param>
        public void GetCaps(XI.Controller controller)
        {
            Capabilities = GamingDeviceCapabilityFlags.None;


            controller.GetCapabilities(XI.DeviceQueryType.Any, out XI.Capabilities capabilities);

            // Get vibration caps.
            var vibrationRanges = new List <GorgonRange>();

            if (capabilities.Vibration.LeftMotorSpeed != 0)
            {
                vibrationRanges.Add(new GorgonRange(0, ushort.MaxValue));
                Capabilities |= GamingDeviceCapabilityFlags.SupportsVibration;
            }

            if (capabilities.Vibration.RightMotorSpeed != 0)
            {
                vibrationRanges.Add(new GorgonRange(0, ushort.MaxValue));
                Capabilities |= GamingDeviceCapabilityFlags.SupportsVibration;
            }

            VibrationMotorRanges = vibrationRanges;

            if (((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.DPadDown) == XI.GamepadButtonFlags.DPadDown) ||
                ((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.DPadUp) == XI.GamepadButtonFlags.DPadUp) ||
                ((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.DPadLeft) == XI.GamepadButtonFlags.DPadLeft) ||
                ((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.DPadRight) == XI.GamepadButtonFlags.DPadRight))
            {
                Capabilities |= GamingDeviceCapabilityFlags.SupportsPOV;
            }

            // Get buttons, and remap to the button indices present in the gaming device control panel app.
            if ((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.A) == XI.GamepadButtonFlags.A)
            {
                SupportedButtons[XI.GamepadButtonFlags.A] = 0;
            }

            if ((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.B) == XI.GamepadButtonFlags.B)
            {
                SupportedButtons[XI.GamepadButtonFlags.B] = 1;
            }

            if ((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.X) == XI.GamepadButtonFlags.X)
            {
                SupportedButtons[XI.GamepadButtonFlags.X] = 2;
            }

            if ((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.Y) == XI.GamepadButtonFlags.Y)
            {
                SupportedButtons[XI.GamepadButtonFlags.Y] = 3;
            }

            if ((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.LeftShoulder) == XI.GamepadButtonFlags.LeftShoulder)
            {
                SupportedButtons[XI.GamepadButtonFlags.LeftShoulder] = 4;
            }

            if ((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.RightShoulder) == XI.GamepadButtonFlags.RightShoulder)
            {
                SupportedButtons[XI.GamepadButtonFlags.RightShoulder] = 5;
            }

            if ((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.Back) == XI.GamepadButtonFlags.Back)
            {
                SupportedButtons[XI.GamepadButtonFlags.Back] = 6;
            }

            if ((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.Start) == XI.GamepadButtonFlags.Start)
            {
                SupportedButtons[XI.GamepadButtonFlags.Start] = 7;
            }

            if ((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.LeftThumb) == XI.GamepadButtonFlags.LeftThumb)
            {
                SupportedButtons[XI.GamepadButtonFlags.LeftThumb] = 8;
            }

            if ((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.RightThumb) == XI.GamepadButtonFlags.RightThumb)
            {
                SupportedButtons[XI.GamepadButtonFlags.RightThumb] = 9;
            }

            if ((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.DPadUp) == XI.GamepadButtonFlags.DPadUp)
            {
                SupportedButtons[XI.GamepadButtonFlags.DPadUp] = 10;
            }

            if ((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.DPadRight) == XI.GamepadButtonFlags.DPadRight)
            {
                SupportedButtons[XI.GamepadButtonFlags.DPadRight] = 11;
            }

            if ((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.DPadDown) == XI.GamepadButtonFlags.DPadDown)
            {
                SupportedButtons[XI.GamepadButtonFlags.DPadDown] = 12;
            }

            if ((capabilities.Gamepad.Buttons & XI.GamepadButtonFlags.DPadLeft) == XI.GamepadButtonFlags.DPadLeft)
            {
                SupportedButtons[XI.GamepadButtonFlags.DPadLeft] = 13;
            }

            // Find out the ranges for each axis.
            var axes = new Dictionary <GamingDeviceAxis, GorgonRange>(new GorgonGamingDeviceAxisEqualityComparer());

            if (capabilities.Gamepad.LeftThumbX != 0)
            {
                axes[GamingDeviceAxis.XAxis] = new GorgonRange(short.MinValue, short.MaxValue);
            }

            if (capabilities.Gamepad.LeftThumbY != 0)
            {
                axes[GamingDeviceAxis.YAxis] = new GorgonRange(short.MinValue, short.MaxValue);
            }

            if (capabilities.Gamepad.RightThumbX != 0)
            {
                axes[GamingDeviceAxis.XAxis2] = new GorgonRange(short.MinValue, short.MaxValue);
                Capabilities |= GamingDeviceCapabilityFlags.SupportsSecondaryXAxis;
            }

            if (capabilities.Gamepad.RightThumbY != 0)
            {
                axes[GamingDeviceAxis.YAxis2] = new GorgonRange(short.MinValue, short.MaxValue);
                Capabilities |= GamingDeviceCapabilityFlags.SupportsSecondaryYAxis;
            }

            if (capabilities.Gamepad.LeftTrigger != 0)
            {
                axes[GamingDeviceAxis.LeftTrigger] = new GorgonRange(0, byte.MaxValue);
                Capabilities |= GamingDeviceCapabilityFlags.SupportsRudder;
            }

            if (capabilities.Gamepad.RightTrigger != 0)
            {
                axes[GamingDeviceAxis.RightTrigger] = new GorgonRange(0, byte.MaxValue);
                Capabilities |= GamingDeviceCapabilityFlags.SupportsThrottle;
            }

            AxisInfo = new GorgonGamingDeviceAxisList <GorgonGamingDeviceAxisInfo>(axes.Select(item => new GorgonGamingDeviceAxisInfo(item.Key, item.Value, 0)));
        }
        /// <summary>
        /// Function to retrieve the capabilities from the DirectInput joystick.
        /// </summary>
        /// <param name="joystick">The DirectInput joystick to evaluate.</param>
        public void GetDeviceCaps(DI.Joystick joystick)
        {
            var defaults   = new Dictionary <GamingDeviceAxis, int>(new GorgonGamingDeviceAxisEqualityComparer());
            var axisRanges = new Dictionary <GamingDeviceAxis, GorgonRange>(new GorgonGamingDeviceAxisEqualityComparer());

            ProductID      = joystick.Properties.ProductId;
            ManufacturerID = joystick.Properties.VendorId;
            ButtonCount    = joystick.Capabilities.ButtonCount;
            POVCount       = joystick.Capabilities.PovCount;
            Capabilities   = POVCount > 0 ? GamingDeviceCapabilityFlags.SupportsPOV : GamingDeviceCapabilityFlags.None;

            IList <DI.DeviceObjectInstance> axisInfo = joystick.GetObjects(DI.DeviceObjectTypeFlags.Axis);

            foreach (DI.DeviceObjectInstance axis in axisInfo)
            {
                var usage = (HIDUsage)axis.Usage;
                DI.ObjectProperties properties = joystick.GetObjectPropertiesById(axis.ObjectId);

                // Skip this axis if retrieving the properties results in failure.
                if (properties == null)
                {
                    continue;
                }

                var range    = new GorgonRange(properties.Range.Minimum, properties.Range.Maximum);
                int midPoint = ((range.Range + 1) / 2) + range.Minimum;

                switch (usage)
                {
                case HIDUsage.X:
                    AxisMappings[GamingDeviceAxis.XAxis] = axis.ObjectId;
                    axisRanges[GamingDeviceAxis.XAxis]   = range;
                    defaults[GamingDeviceAxis.XAxis]     = range.Minimum < 0 ? 0 : midPoint;
                    break;

                case HIDUsage.Y:
                    AxisMappings[GamingDeviceAxis.YAxis] = axis.ObjectId;
                    axisRanges[GamingDeviceAxis.YAxis]   = range;
                    defaults[GamingDeviceAxis.YAxis]     = range.Minimum < 0 ? 0 : midPoint;
                    break;

                case HIDUsage.Slider:
                    AxisMappings[GamingDeviceAxis.Throttle] = axis.ObjectId;
                    axisRanges[GamingDeviceAxis.Throttle]   = range;
                    defaults[GamingDeviceAxis.Throttle]     = 0;
                    Capabilities |= GamingDeviceCapabilityFlags.SupportsThrottle;
                    break;

                case HIDUsage.Z:
                    AxisMappings[GamingDeviceAxis.ZAxis] = axis.ObjectId;
                    axisRanges[GamingDeviceAxis.ZAxis]   = range;
                    defaults[GamingDeviceAxis.ZAxis]     = range.Minimum < 0 ? 0 : midPoint;
                    Capabilities |= GamingDeviceCapabilityFlags.SupportsZAxis;
                    break;

                case HIDUsage.RelativeX:
                    AxisMappings[GamingDeviceAxis.XAxis2] = axis.ObjectId;
                    axisRanges[GamingDeviceAxis.XAxis2]   = range;
                    Capabilities |= GamingDeviceCapabilityFlags.SupportsSecondaryXAxis;
                    defaults[GamingDeviceAxis.XAxis2] = midPoint;
                    break;

                case HIDUsage.RelativeY:
                    AxisMappings[GamingDeviceAxis.YAxis2] = axis.ObjectId;
                    axisRanges[GamingDeviceAxis.YAxis2]   = range;
                    Capabilities |= GamingDeviceCapabilityFlags.SupportsSecondaryYAxis;
                    defaults[GamingDeviceAxis.YAxis2] = midPoint;
                    break;

                case HIDUsage.RelativeZ:
                    AxisMappings[GamingDeviceAxis.ZAxis2] = axis.ObjectId;
                    axisRanges[GamingDeviceAxis.ZAxis2]   = range;
                    Capabilities |= GamingDeviceCapabilityFlags.SupportsRudder;
                    defaults[GamingDeviceAxis.ZAxis2] = 0;
                    break;
                }
            }

            AxisInfo = new GorgonGamingDeviceAxisList <GorgonGamingDeviceAxisInfo>(
                axisRanges.Select(item => new GorgonGamingDeviceAxisInfo(item.Key, item.Value, defaults[item.Key])));
        }