Changed all namespaces to file-scope

This commit is contained in:
DarthAffe committed 2021-11-13 17:35:08 +01:00
1 parent a0c6ccebea
commit 30624035f1
353 files changed
+35775 -36129

No files matched your search

+35 -36
View File
@@ -4,47 +4,46 @@ using System;
using System.Linq;
using System.Runtime.InteropServices;
namespace RGB.NET.Devices.Logitech.HID
namespace RGB.NET.Devices.Logitech.HID;
internal static class Extensions
{
internal static class Extensions
internal static Span<byte> AsSpan<T>(this ref T val)
where T : unmanaged
{
internal static Span<byte> AsSpan<T>(this ref T val)
where T : unmanaged
{
Span<T> valSpan = MemoryMarshal.CreateSpan(ref val, 1);
return MemoryMarshal.Cast<T, byte>(valSpan);
}
Span<T> valSpan = MemoryMarshal.CreateSpan(ref val, 1);
return MemoryMarshal.Cast<T, byte>(valSpan);
}
internal static uint GetUsagePage(this HidDevice device)
internal static uint GetUsagePage(this HidDevice device)
{
try
{
try
{
return device.GetItemByType(ItemType.Global)?.DataValue ?? uint.MaxValue;
}
catch
{
return uint.MaxValue;
}
return device.GetItemByType(ItemType.Global)?.DataValue ?? uint.MaxValue;
}
internal static uint GetUsage(this HidDevice device)
catch
{
try
{
return device.GetItemByType(ItemType.Local)?.DataValue ?? uint.MaxValue;
}
catch
{
return uint.MaxValue;
}
}
private static EncodedItem? GetItemByType(this HidDevice device, ItemType itemType)
{
byte[] descriptor = device.GetRawReportDescriptor();
return EncodedItem.DecodeItems(descriptor, 0, descriptor.Length)
.Where(de => (de.TagForLocal == LocalItemTag.Usage) && (de.TagForGlobal == GlobalItemTag.UsagePage))
.FirstOrDefault(de => de.ItemType == itemType);
return uint.MaxValue;
}
}
}
internal static uint GetUsage(this HidDevice device)
{
try
{
return device.GetItemByType(ItemType.Local)?.DataValue ?? uint.MaxValue;
}
catch
{
return uint.MaxValue;
}
}
private static EncodedItem? GetItemByType(this HidDevice device, ItemType itemType)
{
byte[] descriptor = device.GetRawReportDescriptor();
return EncodedItem.DecodeItems(descriptor, 0, descriptor.Length)
.Where(de => (de.TagForLocal == LocalItemTag.Usage) && (de.TagForGlobal == GlobalItemTag.UsagePage))
.FirstOrDefault(de => de.ItemType == itemType);
}
}
+69 -70
View File
@@ -1,73 +1,72 @@
using System.Runtime.InteropServices;
namespace RGB.NET.Devices.Logitech.HID
namespace RGB.NET.Devices.Logitech.HID;
[StructLayout(LayoutKind.Sequential, Pack = 0, Size = 64)]
internal struct FapResponse
{
[StructLayout(LayoutKind.Sequential, Pack = 0, Size = 64)]
internal struct FapResponse
{
public byte Command;
public byte DeviceIndex;
public byte FeatureIndex;
public byte FeatureCommand;
public byte Data00;
public byte Data01;
public byte Data02;
public byte Data03;
public byte Data04;
public byte Data05;
public byte Data06;
public byte Data07;
public byte Data08;
public byte Data09;
public byte Data10;
public byte Data11;
public byte Data12;
public byte Data13;
public byte Data14;
public byte Data15;
public byte Data16;
public byte Data17;
public byte Data18;
public byte Data19;
public byte Data20;
public byte Data21;
public byte Data22;
public byte Data23;
public byte Data24;
public byte Data25;
public byte Data26;
public byte Data27;
public byte Data28;
public byte Data29;
public byte Data30;
public byte Data31;
public byte Data32;
public byte Data33;
public byte Data34;
public byte Data35;
public byte Data36;
public byte Data37;
public byte Data38;
public byte Data39;
public byte Data40;
public byte Data41;
public byte Data42;
public byte Data43;
public byte Data44;
public byte Data45;
public byte Data46;
public byte Data47;
public byte Data48;
public byte Data49;
public byte Data50;
public byte Data51;
public byte Data52;
public byte Data53;
public byte Data54;
public byte Data55;
public byte Data56;
public byte Data57;
public byte Data58;
public byte Data59;
}
}
public byte Command;
public byte DeviceIndex;
public byte FeatureIndex;
public byte FeatureCommand;
public byte Data00;
public byte Data01;
public byte Data02;
public byte Data03;
public byte Data04;
public byte Data05;
public byte Data06;
public byte Data07;
public byte Data08;
public byte Data09;
public byte Data10;
public byte Data11;
public byte Data12;
public byte Data13;
public byte Data14;
public byte Data15;
public byte Data16;
public byte Data17;
public byte Data18;
public byte Data19;
public byte Data20;
public byte Data21;
public byte Data22;
public byte Data23;
public byte Data24;
public byte Data25;
public byte Data26;
public byte Data27;
public byte Data28;
public byte Data29;
public byte Data30;
public byte Data31;
public byte Data32;
public byte Data33;
public byte Data34;
public byte Data35;
public byte Data36;
public byte Data37;
public byte Data38;
public byte Data39;
public byte Data40;
public byte Data41;
public byte Data42;
public byte Data43;
public byte Data44;
public byte Data45;
public byte Data46;
public byte Data47;
public byte Data48;
public byte Data49;
public byte Data50;
public byte Data51;
public byte Data52;
public byte Data53;
public byte Data54;
public byte Data55;
public byte Data56;
public byte Data57;
public byte Data58;
public byte Data59;
}
+35 -36
View File
@@ -1,42 +1,41 @@
using System.Runtime.InteropServices;
namespace RGB.NET.Devices.Logitech.HID
namespace RGB.NET.Devices.Logitech.HID;
[StructLayout(LayoutKind.Sequential, Pack = 0, Size = 7)]
internal struct FapShortRequest
{
[StructLayout(LayoutKind.Sequential, Pack = 0, Size = 7)]
internal struct FapShortRequest
#region Constants
private const byte LOGITECH_SHORT_MESSAGE = 0x10;
#endregion
#region Properties & Fields
public byte ReportId;
public byte DeviceIndex;
public byte FeatureIndex;
public byte FeatureCommand;
public byte Data0;
public byte Data1;
public byte Data2;
#endregion
#region Constructors
public void Init(byte deviceIndex, byte featureIndex)
{
#region Constants
this.DeviceIndex = deviceIndex;
this.FeatureIndex = featureIndex;
private const byte LOGITECH_SHORT_MESSAGE = 0x10;
#endregion
#region Properties & Fields
public byte ReportId;
public byte DeviceIndex;
public byte FeatureIndex;
public byte FeatureCommand;
public byte Data0;
public byte Data1;
public byte Data2;
#endregion
#region Constructors
public void Init(byte deviceIndex, byte featureIndex)
{
this.DeviceIndex = deviceIndex;
this.FeatureIndex = featureIndex;
ReportId = LOGITECH_SHORT_MESSAGE;
FeatureCommand = 0;
Data0 = 0;
Data1 = 0;
Data2 = 0;
}
#endregion
ReportId = LOGITECH_SHORT_MESSAGE;
FeatureCommand = 0;
Data0 = 0;
Data1 = 0;
Data2 = 0;
}
}
#endregion
}
@@ -6,177 +6,176 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace RGB.NET.Devices.Logitech.HID
namespace RGB.NET.Devices.Logitech.HID;
/// <summary>
/// Represents a loaded for logitech HID-devices.
/// </summary>
/// <typeparam name="TLed">The type of the identifier leds are mapped to.</typeparam>
/// <typeparam name="TData">The type of the custom data added to the HID-device.</typeparam>
public class LightspeedHIDLoader<TLed, TData> : IEnumerable<HIDDeviceDefinition<TLed, TData>>
where TLed : notnull
{
#region Constants
private const int VENDOR_ID = 0x046D;
// ReSharper disable once StaticMemberInGenericType - This is used like a const
private static readonly List<int> RECEIVER_PIDS = new()
{
0xC539,
0xC53A,
0xC541,
0xC545
};
#endregion
#region Properties & Fields
private readonly Dictionary<int, HIDDeviceDefinition<TLed, TData>> _deviceDefinitions = new();
/// <summary>
/// Represents a loaded for logitech HID-devices.
/// Gets the vendor id used for this loader.
/// </summary>
/// <typeparam name="TLed">The type of the identifier leds are mapped to.</typeparam>
/// <typeparam name="TData">The type of the custom data added to the HID-device.</typeparam>
public class LightspeedHIDLoader<TLed, TData> : IEnumerable<HIDDeviceDefinition<TLed, TData>>
where TLed : notnull
public int VendorId => VENDOR_ID;
/// <summary>
/// Gets or sets the filter used to determine which devices should be loaded.
/// </summary>
public RGBDeviceType LoadFilter { get; set; } = RGBDeviceType.All;
#endregion
#region Methods
/// <summary>
/// Adds a new <see cref="HIDDeviceDefinition{TLed,TData}"/> to this loader.
/// </summary>
/// <param name="virtualPid">The virtual product id of the HID-device.</param>
/// <param name="deviceType">The type of the device.</param>
/// <param name="name">The name of the device.</param>
/// <param name="ledMapping">The mapping of the leds of the device.</param>
/// <param name="customData">Some custom data to attach to the device.</param>
public void Add(int virtualPid, RGBDeviceType deviceType, string name, LedMapping<TLed> ledMapping, TData customData)
=> _deviceDefinitions.Add(virtualPid, new HIDDeviceDefinition<TLed, TData>(virtualPid, deviceType, name, ledMapping, customData));
/// <summary>
/// Gets a enumerable containing all devices from the definition-list that are connected and match the <see cref="LoadFilter"/>.
/// </summary>
/// <returns>The enumerable containing the connected devices.</returns>
public IEnumerable<HIDDeviceDefinition<TLed, TData>> GetConnectedDevices()
{
#region Constants
private const int VENDOR_ID = 0x046D;
// ReSharper disable once StaticMemberInGenericType - This is used like a const
private static readonly List<int> RECEIVER_PIDS = new()
foreach (int device in Detect())
{
0xC539,
0xC53A,
0xC541,
0xC545
};
#endregion
#region Properties & Fields
private readonly Dictionary<int, HIDDeviceDefinition<TLed, TData>> _deviceDefinitions = new();
/// <summary>
/// Gets the vendor id used for this loader.
/// </summary>
public int VendorId => VENDOR_ID;
/// <summary>
/// Gets or sets the filter used to determine which devices should be loaded.
/// </summary>
public RGBDeviceType LoadFilter { get; set; } = RGBDeviceType.All;
#endregion
#region Methods
/// <summary>
/// Adds a new <see cref="HIDDeviceDefinition{TLed,TData}"/> to this loader.
/// </summary>
/// <param name="virtualPid">The virtual product id of the HID-device.</param>
/// <param name="deviceType">The type of the device.</param>
/// <param name="name">The name of the device.</param>
/// <param name="ledMapping">The mapping of the leds of the device.</param>
/// <param name="customData">Some custom data to attach to the device.</param>
public void Add(int virtualPid, RGBDeviceType deviceType, string name, LedMapping<TLed> ledMapping, TData customData)
=> _deviceDefinitions.Add(virtualPid, new HIDDeviceDefinition<TLed, TData>(virtualPid, deviceType, name, ledMapping, customData));
/// <summary>
/// Gets a enumerable containing all devices from the definition-list that are connected and match the <see cref="LoadFilter"/>.
/// </summary>
/// <returns>The enumerable containing the connected devices.</returns>
public IEnumerable<HIDDeviceDefinition<TLed, TData>> GetConnectedDevices()
{
foreach (int device in Detect())
{
if (_deviceDefinitions.TryGetValue(device, out HIDDeviceDefinition<TLed, TData>? definition))
if (LoadFilter.HasFlag(definition.DeviceType))
yield return definition;
}
if (_deviceDefinitions.TryGetValue(device, out HIDDeviceDefinition<TLed, TData>? definition))
if (LoadFilter.HasFlag(definition.DeviceType))
yield return definition;
}
}
/// <summary>
/// Gets a enumerable containing all the first device of each group of devices from the definition-list that are connected and match the <see cref="LoadFilter"/>.
/// The grouping is done by the specified function.
/// </summary>
/// <typeparam name="TKey">The type of the key used to group the devices.</typeparam>
/// <param name="groupBy">The function grouping the devices.</param>
/// <returns>The enumerable containing the selected devices.</returns>
public IEnumerable<HIDDeviceDefinition<TLed, TData>> GetConnectedDevices<TKey>(Func<HIDDeviceDefinition<TLed, TData>, TKey> groupBy)
=> GetConnectedDevices().GroupBy(groupBy)
.Select(group => group.First());
/// <summary>
/// Gets a enumerable containing all the first device of each group of devices from the definition-list that are connected and match the <see cref="LoadFilter"/>.
/// The grouping is done by the specified function.
/// </summary>
/// <typeparam name="TKey">The type of the key used to group the devices.</typeparam>
/// <param name="groupBy">The function grouping the devices.</param>
/// <returns>The enumerable containing the selected devices.</returns>
public IEnumerable<HIDDeviceDefinition<TLed, TData>> GetConnectedDevices<TKey>(Func<HIDDeviceDefinition<TLed, TData>, TKey> groupBy)
=> GetConnectedDevices().GroupBy(groupBy)
.Select(group => group.First());
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
/// <inheritdoc />
public IEnumerator<HIDDeviceDefinition<TLed, TData>> GetEnumerator() => _deviceDefinitions.Values.GetEnumerator();
/// <inheritdoc />
public IEnumerator<HIDDeviceDefinition<TLed, TData>> GetEnumerator() => _deviceDefinitions.Values.GetEnumerator();
#endregion
#endregion
#region Private Methods
#region Private Methods
private IEnumerable<int> Detect() => RECEIVER_PIDS.SelectMany(Detect);
private IEnumerable<int> Detect() => RECEIVER_PIDS.SelectMany(Detect);
private IEnumerable<int> Detect(int pid)
private IEnumerable<int> Detect(int pid)
{
Dictionary<byte, HidDevice> deviceUsages = DeviceList.Local
.GetHidDevices(VendorId, pid)
.Where(d => d.DevicePath.Contains("mi_02"))
.ToDictionary(x => (byte)x.GetUsage(), x => x);
foreach ((int wirelessPid, byte _) in GetWirelessDevices(deviceUsages))
yield return wirelessPid;
}
private Dictionary<int, byte> GetWirelessDevices(IReadOnlyDictionary<byte, HidDevice> deviceUsages)
{
const byte LOGITECH_RECEIVER_ADDRESS = 0xFF;
const byte LOGITECH_SET_REGISTER_REQUEST = 0x80;
const byte LOGITECH_GET_REGISTER_REQUEST = 0x81;
Dictionary<int, byte> map = new();
if (deviceUsages.TryGetValue(1, out HidDevice? device))
{
Dictionary<byte, HidDevice> deviceUsages = DeviceList.Local
.GetHidDevices(VendorId, pid)
.Where(d => d.DevicePath.Contains("mi_02"))
.ToDictionary(x => (byte)x.GetUsage(), x => x);
HidStream? stream = device.Open();
foreach ((int wirelessPid, byte _) in GetWirelessDevices(deviceUsages))
yield return wirelessPid;
}
FapResponse response = new();
private Dictionary<int, byte> GetWirelessDevices(IReadOnlyDictionary<byte, HidDevice> deviceUsages)
{
const byte LOGITECH_RECEIVER_ADDRESS = 0xFF;
const byte LOGITECH_SET_REGISTER_REQUEST = 0x80;
const byte LOGITECH_GET_REGISTER_REQUEST = 0x81;
FapShortRequest getConnectedDevices = new();
getConnectedDevices.Init(LOGITECH_RECEIVER_ADDRESS, LOGITECH_GET_REGISTER_REQUEST);
Dictionary<int, byte> map = new();
stream.Write(getConnectedDevices.AsSpan());
stream.Read(response.AsSpan());
if (deviceUsages.TryGetValue(1, out HidDevice? device))
bool wirelessNotifications = (response.Data01 & 1) == 1;
if (!wirelessNotifications)
{
HidStream? stream = device.Open();
FapResponse response = new();
FapShortRequest getConnectedDevices = new();
getConnectedDevices.Init(LOGITECH_RECEIVER_ADDRESS, LOGITECH_GET_REGISTER_REQUEST);
stream.Write(getConnectedDevices.AsSpan());
stream.Read(response.AsSpan());
bool wirelessNotifications = (response.Data01 & 1) == 1;
if (!wirelessNotifications)
{
response = new FapResponse();
getConnectedDevices.Init(LOGITECH_RECEIVER_ADDRESS, LOGITECH_SET_REGISTER_REQUEST);
getConnectedDevices.Data1 = 1;
stream.Write(getConnectedDevices.AsSpan());
stream.Read(response.AsSpan());
if (getConnectedDevices.FeatureIndex == 0x8f)
{
//error??
}
}
response = new FapResponse();
getConnectedDevices.Init(LOGITECH_RECEIVER_ADDRESS, LOGITECH_GET_REGISTER_REQUEST);
getConnectedDevices.FeatureCommand = 0x02;
getConnectedDevices.Init(LOGITECH_RECEIVER_ADDRESS, LOGITECH_SET_REGISTER_REQUEST);
getConnectedDevices.Data1 = 1;
stream.Write(getConnectedDevices.AsSpan());
stream.Read(response.AsSpan());
int deviceCount = response.Data01;
if (deviceCount > 0)
if (getConnectedDevices.FeatureIndex == 0x8f)
{
//log "Faking a reconnect to get device list"
deviceCount++;
getConnectedDevices.Init(LOGITECH_RECEIVER_ADDRESS, LOGITECH_SET_REGISTER_REQUEST);
getConnectedDevices.FeatureCommand = 0x02;
getConnectedDevices.Data0 = 0x02;
stream.Write(getConnectedDevices.AsSpan());
for (int i = 0; i < deviceCount; i++)
{
FapResponse devices = new();
stream.Read(devices.AsSpan());
int wirelessPid = (devices.Data02 << 8) | devices.Data01;
if (devices.DeviceIndex != 0xff)
map.Add(wirelessPid, devices.DeviceIndex);
}
//error??
}
}
return map;
response = new FapResponse();
getConnectedDevices.Init(LOGITECH_RECEIVER_ADDRESS, LOGITECH_GET_REGISTER_REQUEST);
getConnectedDevices.FeatureCommand = 0x02;
stream.Write(getConnectedDevices.AsSpan());
stream.Read(response.AsSpan());
int deviceCount = response.Data01;
if (deviceCount > 0)
{
//log "Faking a reconnect to get device list"
deviceCount++;
getConnectedDevices.Init(LOGITECH_RECEIVER_ADDRESS, LOGITECH_SET_REGISTER_REQUEST);
getConnectedDevices.FeatureCommand = 0x02;
getConnectedDevices.Data0 = 0x02;
stream.Write(getConnectedDevices.AsSpan());
for (int i = 0; i < deviceCount; i++)
{
FapResponse devices = new();
stream.Read(devices.AsSpan());
int wirelessPid = (devices.Data02 << 8) | devices.Data01;
if (devices.DeviceIndex != 0xff)
map.Add(wirelessPid, devices.DeviceIndex);
}
}
}
#endregion
return map;
}
}
#endregion
}