Skip to content

Commit ae5f092

Browse files
authored
[+] Adx hot plug (#108)
1 parent 23dad87 commit ae5f092

File tree

1 file changed

+123
-22
lines changed

1 file changed

+123
-22
lines changed

AquaMai.Mods/GameSystem/AdxHidInput.cs

Lines changed: 123 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.IO.Pipes;
44
using System.Linq;
@@ -31,22 +31,121 @@ public class AdxHidInput
3131
private static byte[,] inputBufPending = new byte[2, 32];
3232
private static double[] td = [0, 0];
3333
private static bool tdEnabled, keyEnabled, pipeEnabled;
34+
private static bool[] hidThreadRunning = [false, false];
35+
36+
private static bool TryConnectDevice(int p)
37+
{
38+
var device = p == 0
39+
? HidDevices.Enumerate(0x2E3C, [0x5750, 0x5767]).FirstOrDefault(it => !it.DevicePath.EndsWith("kbd"))
40+
: HidDevices.Enumerate(0x2E4C, 0x5750).Concat(HidDevices.Enumerate(0x2E3C, 0x5768)).FirstOrDefault(it => !it.DevicePath.EndsWith("kbd"));
41+
42+
if (device == null) return false;
43+
44+
adxController[p] = device;
45+
device.OpenDevice();
46+
MelonLogger.Msg($"[HidInput] Device {p + 1}P connected");
47+
48+
return true;
49+
}
50+
51+
private static bool IsDeviceAvailable(int p)
52+
{
53+
var device = adxController[p];
54+
if (device == null) return false;
55+
56+
try
57+
{
58+
return device.IsConnected;
59+
}
60+
catch
61+
{
62+
return false;
63+
}
64+
}
65+
66+
private static void DisconnectDevice(int p)
67+
{
68+
var device = adxController[p];
69+
if (device == null) return;
70+
71+
try
72+
{
73+
device.CloseDevice();
74+
}
75+
catch
76+
{
77+
// ignore
78+
}
79+
80+
adxController[p] = null;
81+
82+
for (int i = 0; i < 32; i++)
83+
{
84+
inputBuf[p, i] = 0;
85+
inputBufPending[p, i] = 0;
86+
}
87+
88+
MelonLogger.Msg($"[HidInput] Device {p + 1}P disconnected");
89+
}
90+
91+
private static bool NeedsButtonInput(int p)
92+
{
93+
var device = adxController[p];
94+
if (device == null) return false;
95+
try
96+
{
97+
return device.Attributes.ProductId is not (0x5767 or 0x5768);
98+
}
99+
catch
100+
{
101+
return false;
102+
}
103+
}
34104

35105
private static void HidInputThread(int p)
36106
{
37107
while (true)
38108
{
39-
if (adxController[p] == null) return;
40-
var report1P = adxController[p].Read();
41-
if (report1P.Status != HidDeviceData.ReadStatus.Success || report1P.Data.Length <= 13) continue;
42-
for (int i = 0; i < 14; i++)
109+
while (!IsDeviceAvailable(p))
110+
{
111+
Thread.Sleep(500);
112+
TryConnectDevice(p);
113+
}
114+
115+
if (!NeedsButtonInput(p))
43116
{
44-
var newState = report1P.Data[i];
45-
if (newState == 1 && inputBuf[p, i] == 0)
117+
Thread.Sleep(500);
118+
continue;
119+
}
120+
121+
var device = adxController[p];
122+
if (device == null) continue;
123+
124+
try
125+
{
126+
var report = device.Read();
127+
128+
if (report.Status != HidDeviceData.ReadStatus.Success)
129+
{
130+
DisconnectDevice(p);
131+
continue;
132+
}
133+
134+
if (report.Data.Length <= 13) continue;
135+
136+
for (int i = 0; i < 14; i++)
46137
{
47-
inputBufPending[p, i] = 1;
138+
var newState = report.Data[i];
139+
if (newState == 1 && inputBuf[p, i] == 0)
140+
{
141+
inputBufPending[p, i] = 1;
142+
}
143+
inputBuf[p, i] = newState;
48144
}
49-
inputBuf[p, i] = newState;
145+
}
146+
catch
147+
{
148+
DisconnectDevice(p);
50149
}
51150
}
52151
}
@@ -99,28 +198,30 @@ private static void TdInit(int p)
99198

100199
public static void OnBeforeEnableCheck()
101200
{
102-
adxController[0] = HidDevices.Enumerate(0x2E3C, [0x5750, 0x5767]).FirstOrDefault(it => !it.DevicePath.EndsWith("kbd"));
103-
adxController[1] = HidDevices.Enumerate(0x2E4C, 0x5750).Concat(HidDevices.Enumerate(0x2E3C, 0x5768)).FirstOrDefault(it => !it.DevicePath.EndsWith("kbd"));
201+
TryConnectDevice(0);
202+
TryConnectDevice(1);
104203

105-
if (adxController[0] != null)
204+
for (int i = 0; i < 2; i++)
106205
{
107-
MelonLogger.Msg("[HidInput] Open HID 1P OK");
206+
if (adxController[i] != null)
207+
{
208+
TdInit(i);
209+
}
108210
}
109211

110-
if (adxController[1] != null)
111-
{
112-
MelonLogger.Msg("[HidInput] Open HID 2P OK");
113-
}
212+
if (disableButtons) return;
114213

115214
for (int i = 0; i < 2; i++)
116215
{
117-
if (adxController[i] == null) continue;
118-
TdInit(i);
119-
if (adxController[i].Attributes.ProductId is 0x5767 or 0x5768) continue;
120-
if (disableButtons) continue;
216+
if (hidThreadRunning[i]) continue;
217+
121218
keyEnabled = true;
219+
hidThreadRunning[i] = true;
122220
var p = i;
123-
Thread hidThread = new Thread(() => HidInputThread(p));
221+
var hidThread = new Thread(() => HidInputThread(p))
222+
{
223+
IsBackground = true
224+
};
124225
hidThread.Start();
125226
}
126227
}

0 commit comments

Comments
 (0)