通过GIP软件断开Xbox Series控制器连接:技术深度解析
Steam大画面模式在客厅游戏中很方便,但存在一些不足:它不会切换音频输出,不会关闭夜间模式,退出时也不会断开Xbox Series控制器的连接。一位开发者用C#创建了Big Picture Manager来实现自动化。该应用监控Steam大画面窗口的启动,切换音频设备,管理Windows注册表以处理夜间模式,并解决了控制器问题。
对于音频,进入时会设置目标设备,退出时恢复原设备。夜间模式通过直接写入注册表来禁用,并自动恢复。
Xbox Series:连接与容错
Xbox Series控制器可通过蓝牙、Xbox无线适配器(2.4 GHz)或USB连接。断开连接的问题可以通过完全禁用蓝牙来解决,但这并非理想方案。目标是通过GIP(游戏输入协议)选择性断开连接。
微软在2024年发布了GameInput文档,统一了XInput、DirectInput、Raw Input、HID和WinRT。GIP是游戏设备的传输协议。设置设备状态(0x04)命令将设备切换到GIP关闭状态。
在C#中实现XboxGIP访问
通过\\.\XboxGIP以读写权限打开接口访问。代码使用P/Invoke调用kernel32.dll:CreateFileW、DeviceIoControl、ReadFile、WriteFile。
重新初始化和发送断开连接命令的示例代码:
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)。
- 字节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
暂无评论。