XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

LogiBoardToolBox

【WinUI】罗技鼠标板载驱动程序

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Buffers.Binary;

namespace LogiBoardToolBox.Core.Onboard;

public sealed record OnboardCapabilities(byte MemoryModel, byte ProfileFormat, byte MacroFormat,
    byte ProfileCount, byte FactoryProfileCount, byte ButtonCount, byte SectorCount,
    ushort SectorSize, byte MechanicalLayout, byte VariousInfo)
{
    public bool HasGShift => (MechanicalLayout & 3) == 2;
    public bool HasDpiShift => ((MechanicalLayout >> 2) & 3) == 2;
    // Format 10 is observed on this G502 X PLUS, not yet covered by upstream codecs.
    // Only the matching geometry and the unchanged button/name regions are enabled,
    // behind an explicit experimental switch in the write planner.
    public bool IsExperimental => ProfileFormat == 10;
    public bool CanEditPerformance => CanEditProfiles;
    public bool CanEditLighting => CanEditProfiles && ProfileFormat >= 2;
    public int BindingRecordCount => IsExperimental ? 13 : 16;
    public int AssignableButtonCount => IsExperimental ? Math.Min(BindingRecordCount, ButtonCount + 2) : ButtonCount;
    public bool HasRecognizedLayout => ProfileFormat is >= 1 and <= 5 ||
        ProfileFormat == 10 && ProfileCount == 5 && ButtonCount == 11 && SectorCount == 16 && SectorSize == 255 && MechanicalLayout == 0x0A;
    public bool CanEditProfiles => MemoryModel == 1 && HasRecognizedLayout &&
        SectorSize is >= 254 and <= 4096 && ButtonCount is > 0 and <= 16 &&
        ProfileCount is > 0 and <= 16 && SectorCount > ProfileCount && (ProfileCount + 1) * 4 + 2 <= SectorSize;
    public bool CanWriteMacros => CanEditProfiles && MacroFormat == 1 && SectorCount > ProfileCount + 1;

    public static OnboardCapabilities Parse(ReadOnlySpan<byte> bytes)
    {
        if (bytes.Length < 11) throw new IOException("板载能力回复长度不足。");
        return new(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6],
            BinaryPrimitives.ReadUInt16BigEndian(bytes[7..]), bytes[9], bytes[10]);
    }

    public string Summary => $"格式 {ProfileFormat} · {ProfileCount} 个配置 · {ButtonCount} 个按键 · {SectorCount} × {SectorSize} 字节 · 宏格式 {MacroFormat}";
}