C#解析USB - HID手柄上摇杆按键数据

1. 了解相关知识

  • ​HID设备通信原理​​:HID设备通过端点报告其状态和数据,设备通过报告描述符来描述数据用途,操作系统通过这个描述符了解设备发送数据的结构。通常一个完整的报告以特定的格式从设备传输至主机。
  • ​Windows API函数​​:在C#中,可使用Windows API函数通过P/Invoke(平台调用)方式来与HID设备交互。

2. 准备工作

  • ​获取设备信息​​:需要知道手柄的VID(Vendor ID)和PID(Product ID),你可以通过设备管理器查看。在代码中可以使用这些信息来找到对应的设备。
  • ​添加引用和定义​​:在项目中添加对System.Runtime.InteropServices的引用,以便使用Windows API函数。

3. 代码实现

定义必要的结构体和API函数
using System;
using System.Runtime.InteropServices;

public class HidDevice
{
    // HID设备信息结构体
    [StructLayout(LayoutKind.Sequential)]
    public struct HidDeviceCaps
    {
        public Int16 UsagePage;
        public Int16 Usage;
        public Int32 VersionNumber;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
        public Int16[] LogicalMinimum;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
        public Int16[] LogicalMaximum;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
        public Int16[] PhysicalMinimum;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
        public Int16[] PhysicalMaximum;
        public Int32 NumberOfButtons;
        public Int32 NumberOfValueCaps;
        public Int32 NumberOfDataIndices;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
        public byte[] Data;
    }

    // 导入Windows API函数
    [DllImport("hid.dll")]
    public static extern Boolean HidD_GetHidGuid(out Guid guid);

    [DllImport("hid.dll")]
    public static extern Boolean HidD_GetDeviceCaps(IntPtr hidDeviceObject, ref HidDeviceCaps capabilities);

    [DllImport("hid.dll")]
    public static extern Boolean HidD_GetInputReport(IntPtr hidDeviceObject, IntPtr buffer, Int32 bufferSize);

    [DllImport("kernel32.dll")]
    public static extern IntPtr CreateFile(String lpFileName, Int32 dwDesiredAccess, Int32 dwShareMode, IntPtr lpSecurityAttributes, Int32 dwCreationDisposition, Int32 dwFlagsAndAttributes, IntPtr hTemplateFile);

    [DllImport("kernel32.dll")]
    public static extern Boolean CloseHandle(IntPtr hObject);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern Boolean ReadFile(IntPtr hFile, IntPtr buffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);
}
实现HID设备的数据读取
public class HidDeviceReader
{
    private IntPtr _hidDeviceHandle;

    public HidDeviceReader(string devicePath)
    {
        // 打开HID设备
        _hidDeviceHandle = CreateFile(devicePath, FileAccess.ReadWrite, FileShare.None, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
        if (_hidDeviceHandle.ToInt32() == -1)
        {
            // 处理错误
            throw new Exception("Unable to open the HID device.");
        }
    }

    public void ReadData(byte[] buffer)
    {
        // 读取HID设备数据
        uint bytesRead;
        ReadFile(_hidDeviceHandle, buffer, (uint)buffer.Length, out bytesRead, IntPtr.Zero);
    }

    public void Close()
    {
        // 关闭HID设备
        if (_hidDeviceHandle != IntPtr.Zero)
        {
            CloseHandle(_hidDeviceHandle);
            _hidDeviceHandle = IntPtr.Zero;
        }
    }
}
使用HidDeviceReader类来读取数据
class Program
{
    static void Main()
    {
        // 这里需要知道你的HID设备的路径,格式为 @"\\.\VID_XXXX&PID_XXXX"
        string hidDevicePath = @"\\.\VID_XXXX&PID_XXXX";
        HidDeviceReader reader = new HidDeviceReader(hidDevicePath);
        try
        {
            // 根据你的HID设备的数据报告大小创建缓冲区,示例大小为64
            byte[] buffer = new byte[64](@ref);
            // 读取数据
            reader.ReadData(buffer);
            // 处理读取到的数据
            ParseJoystickData(buffer);
        }
        finally
        {
            // 确保关闭设备句柄
            reader.Close();
        }
    }

    static void ParseJoystickData(byte[] data)
    {
        // 这里需要根据手柄的报告描述符来解析摇杆按键数据
        // 例如,假设摇杆X轴数据在data[0](@ref),Y轴数据在data[1](@ref)
        // 按键状态在data[2](@ref)的低8位
        int xValue = data[0](@ref);
        int yValue = data[1](@ref);
        byte buttonState = data[2](@ref);

        Console.WriteLine($"X轴位置: {xValue}");
        Console.WriteLine($"Y轴位置: {yValue}");
        Console.WriteLine($"按键状态: {buttonState}");
    }
}

4. 注意事项

  • ​设备路径​​:需要根据实际情况修改hidDevicePath,你可以在设备管理器中找到手柄对应的设备,其路径格式一般为@"\\.\VID_XXXX&PID_XXXX",其中XXXX是十六进制的VID和PID。
  • ​数据报告大小​​:buffer数组的大小需要根据手柄的数据报告大小来确定,不同的手柄可能不同。
  • ​数据解析​​:ParseJoystickData方法中的数据解析逻辑需要根据手柄的报告描述符来编写,不同的手柄数据格式可能不同。你可以参考HID键盘对照表等相关文档来了解数据格式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT技术猿猴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值