返回首页

通过 GIP 在 C# 中禁用 Xbox Series

本文分析了通过 GIP 协议程序化禁用 Xbox Series 控制器。提供了访问 XboxGIP、形成命令和处理响应的 C# 代码。该解决方案集成到 Steam Big Picture 的实用程序中。

GIP 协议:如何程序化关闭 Xbox 控制器
Advertisement 728x90

通过GIP软件断开Xbox Series控制器连接:技术深度解析

Steam大画面模式在客厅游戏中很方便,但存在一些不足:它不会切换音频输出,不会关闭夜间模式,退出时也不会断开Xbox Series控制器的连接。一位开发者用C#创建了Big Picture Manager来实现自动化。该应用监控Steam大画面窗口的启动,切换音频设备,管理Windows注册表以处理夜间模式,并解决了控制器问题。

对于音频,进入时会设置目标设备,退出时恢复原设备。夜间模式通过直接写入注册表来禁用,并自动恢复。

Xbox Series:连接与容错

Xbox Series控制器可通过蓝牙、Xbox无线适配器(2.4 GHz)或USB连接。断开连接的问题可以通过完全禁用蓝牙来解决,但这并非理想方案。目标是通过GIP(游戏输入协议)选择性断开连接。

Google AdInline article slot

微软在2024年发布了GameInput文档,统一了XInput、DirectInput、Raw Input、HID和WinRT。GIP是游戏设备的传输协议。设置设备状态(0x04)命令将设备切换到GIP关闭状态。

在C#中实现XboxGIP访问

通过\\.\XboxGIP以读写权限打开接口访问。代码使用P/Invoke调用kernel32.dll:CreateFileW、DeviceIoControl、ReadFile、WriteFile。

重新初始化和发送断开连接命令的示例代码:

Google AdInline article slot
using System.ComponentModel;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

public class XboxGipController
{
    private const uint GENERIC_READ = 0x80000000;
    private const uint GENERIC_WRITE = 0x40000000;
    private const uint FILE_SHARE_READ = 0x00000001;
    private const uint FILE_SHARE_WRITE = 0x00000002;
    private const uint OPEN_EXISTING = 3;
    private const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;

    private const uint GIP_ADD_REENUMERATE_CALLER_CONTEXT = 0x40001CD0;

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern SafeFileHandle CreateFileW(
        string lpFileName,
        uint dwDesiredAccess,
        uint dwShareMode,
        IntPtr lpSecurityAttributes,
        uint dwCreationDisposition,
        uint dwFlagsAndAttributes,
        IntPtr hTemplateFile
    );

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool DeviceIoControl(
        SafeFileHandle hDevice,
        uint dwIoControlCode,
        IntPtr lpInBuffer,
        uint nInBufferSize,
        IntPtr lpOutBuffer,
        uint nOutBufferSize,
        out uint lpBytesReturned,
        IntPtr lpOverlapped
    );

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool ReadFile(
        SafeFileHandle hFile,
        byte[] lpBuffer,
        uint nNumberOfBytesToRead,
        out uint lpNumberOfBytesRead,
        IntPtr lpOverlapped
    );

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool WriteFile(
        SafeFileHandle hFile,
        byte[] lpBuffer,
        uint nNumberOfBytesToWrite,
        out uint lpNumberOfBytesWritten,
        IntPtr lpOverlapped
    );

    // ... (ProcessGipMessage和ReenumerateGipControllers代码的其余部分)
}

操作序列

  • 打开\\.\XboxGIP的句柄。
  • 调用DeviceIoControl,使用GIP_ADD_REENUMERATE_CALLER_CONTEXT进行重新初始化。
  • 形成断开连接数据包:

- 字节0-7:Xbox控制器标识符(0x7E 0xED 0x82 0xC6 0x8B 0xDA 0x00 0x00)。

- 字节8:命令ID(0x05)。

- 字节9:标志(0x20)。

Google AdInline article slot

- 字节10:序列(0x01)。

- 字节11:有效载荷长度(0x01)。

- 字节12:有效载荷(0x04表示关闭)。

  • 通过WriteFile发送。
  • 通过ReadFile循环读取响应,直到ERROR_NO_MORE_DATA(代码259)。

调试与限制

代码在使用Xbox无线适配器连接时有效。如果设备未就绪,WriteFile可能会失败。ReadFile处理传入的GIP消息进行分析。要实现完全断开连接,需要精确的字节调整和状态处理。

  • 方法的优势:无需系统破解的低级控制。
  • 劣势:依赖GIP文档,驱动程序更新可能导致变化。
  • 建议:在Windows 10/11上测试,监控Win32Exception。

关键要点

  • GameInput和GIP提供对Xbox Series控制器的统一访问。
  • 设置设备状态中的命令0x04将设备切换到关闭状态。
  • C#中的P/Invoke允许通过\\.\XboxGIP发送原始数据包。
  • 在发送命令前,必须通过GIP_ADD_REENUMERATE_CALLER_CONTEXT进行重新初始化。
  • 该方法仅适用于无线适配器,不适用于蓝牙/USB。

— Editorial Team

Advertisement 728x90

继续阅读