Skip to content

Commit 62a024d

Browse files
Implement Accelerometer and Profiler
Update with accelerometer controls for driver driven profiler
1 parent 4212074 commit 62a024d

File tree

8 files changed

+833
-384
lines changed

8 files changed

+833
-384
lines changed

DSHMC/Drivers/DsHidMiniDriver.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,30 @@ public static class DsHidMiniDriver
6464
Guid.Parse("{99ACCB6C-D709-49BB-90EE-278B1B564A4B}"), 2,
6565
typeof(byte));
6666

67+
/// <summary>
68+
/// Unified Device Property to set if should use accelerometer profiler.
69+
/// </summary>
70+
public static DevicePropertyKey EnableProfilerProperty =>
71+
CustomDeviceProperty.CreateCustomDeviceProperty(
72+
Guid.Parse("{99ACCB6C-D709-49BB-90EE-278B1B564A4B}"), 3,
73+
typeof(byte));
74+
75+
/// <summary>
76+
/// Unified Device Property to set accelerometer X axis sensitivity.
77+
/// </summary>
78+
public static DevicePropertyKey AccelXSensitivityProperty =>
79+
CustomDeviceProperty.CreateCustomDeviceProperty(
80+
Guid.Parse("{99ACCB6C-D709-49BB-90EE-278B1B564A4B}"), 4,
81+
typeof(uint));
82+
83+
/// <summary>
84+
/// Unified Device Property to set accelerometer X axis sensitivity.
85+
/// </summary>
86+
public static DevicePropertyKey AccelYSensitivityProperty =>
87+
CustomDeviceProperty.CreateCustomDeviceProperty(
88+
Guid.Parse("{99ACCB6C-D709-49BB-90EE-278B1B564A4B}"), 5,
89+
typeof(uint));
90+
6791
#endregion
6892

6993
#region Common device properties

DSHMC/MVVM/DeviceViewModel.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,54 @@ public bool MuteDigitalPressureButtons
5151
}
5252
}
5353

54+
public bool EnableProfiler
55+
{
56+
get => _device.GetProperty<byte>(DsHidMiniDriver.EnableProfilerProperty) > 0;
57+
set
58+
{
59+
using (var evt = EventWaitHandle.OpenExisting(
60+
$"Global\\DsHidMiniConfigHotReloadEvent{DeviceAddress}"
61+
))
62+
{
63+
_device.SetProperty(DsHidMiniDriver.EnableProfilerProperty, (byte)(value ? 1 : 0));
64+
65+
evt.Set();
66+
}
67+
}
68+
}
69+
70+
public uint AccelXSensitivity
71+
{
72+
get => _device.GetProperty<uint>(DsHidMiniDriver.AccelXSensitivityProperty);
73+
set
74+
{
75+
using (var evt = EventWaitHandle.OpenExisting(
76+
$"Global\\DsHidMiniConfigHotReloadEvent{DeviceAddress}"
77+
))
78+
{
79+
_device.SetProperty(DsHidMiniDriver.AccelXSensitivityProperty, value);
80+
81+
evt.Set();
82+
}
83+
}
84+
}
85+
86+
public uint AccelYSensitivity
87+
{
88+
get => _device.GetProperty<uint>(DsHidMiniDriver.AccelYSensitivityProperty);
89+
set
90+
{
91+
using (var evt = EventWaitHandle.OpenExisting(
92+
$"Global\\DsHidMiniConfigHotReloadEvent{DeviceAddress}"
93+
))
94+
{
95+
_device.SetProperty(DsHidMiniDriver.AccelYSensitivityProperty, value);
96+
97+
evt.Set();
98+
}
99+
}
100+
}
101+
54102
public bool IsHidModeChangeable =>
55103
SecurityUtil.IsElevated /*&& HidEmulationMode != DsHidDeviceMode.XInputHIDCompatible*/;
56104

DSHMC/UI/Devices/DeviceDetailsView.xaml

Lines changed: 536 additions & 384 deletions
Large diffs are not rendered by default.

sys/Device.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,39 @@ VOID DsDevice_HotReloadConfiguration(PDEVICE_CONTEXT Context)
426426
&requiredSize,
427427
&propType
428428
);
429+
430+
WDF_DEVICE_PROPERTY_DATA_INIT(&propData, &DEVPKEY_DsHidMini_HR_EnableProfiler);
431+
432+
(void)WdfDeviceQueryPropertyEx(
433+
device,
434+
&propData,
435+
sizeof(UCHAR),
436+
&Context->Configuration.EnableProfiler,
437+
&requiredSize,
438+
&propType
439+
);
440+
441+
WDF_DEVICE_PROPERTY_DATA_INIT(&propData, &DEVPKEY_DsHidMini_HR_AccelXSensitivity);
442+
443+
(void)WdfDeviceQueryPropertyEx(
444+
device,
445+
&propData,
446+
sizeof(ULONG),
447+
&Context->Configuration.AccelXSensitivity,
448+
&requiredSize,
449+
&propType
450+
);
451+
452+
WDF_DEVICE_PROPERTY_DATA_INIT(&propData, &DEVPKEY_DsHidMini_HR_AccelYSensitivity);
453+
454+
(void)WdfDeviceQueryPropertyEx(
455+
device,
456+
&propData,
457+
sizeof(ULONG),
458+
&Context->Configuration.AccelYSensitivity,
459+
&requiredSize,
460+
&propType
461+
);
429462
}
430463

431464
//

sys/Device.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,11 @@ typedef struct _DEVICE_CONTEXT
238238
//
239239
LARGE_INTEGER BatteryStatusTimestamp;
240240

241+
//
242+
// Timestamp of PS Button hold for profile switching
243+
//
244+
LARGE_INTEGER ProfileSwitcherTimestamp;
245+
241246
union
242247
{
243248
//

sys/DsCommon.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,49 @@ typedef enum _DS_OUTPUT_REPORT_SOURCE
136136

137137
#include <pshpack1.h>
138138

139+
//
140+
//
141+
//
142+
typedef enum _DS_PROFILE_MODE
143+
{
144+
DsProfileModeDefault = 0x00,
145+
DsProfileModea = 0x01,
146+
DsProfileModeb = 0x02,
147+
DsProfileModec = 0x03
148+
149+
} DS_PROFILE_MODE, * PDS_PROFILE_MODE;
150+
151+
//
152+
//
153+
//
154+
typedef enum _DS_ACCEL_AXIS
155+
{
156+
DsAccelX = 0x00,
157+
DsAccelY = 0x01,
158+
DsAccelYtoL2 = 0x02,
159+
DsAccelYtoR2 = 0x03
160+
161+
} DS_ACCEL_AXIS, * PDS_ACCEL_AXIS;
162+
139163
//
140164
// Per device dynamic configuration properties
141165
//
142166
typedef struct _DS_DRIVER_CONFIGURATION
143167
{
144168
/** The HID device mode */
145169
DS_HID_DEVICE_MODE HidDeviceMode;
170+
171+
/** Which profile mode to use */
172+
DS_PROFILE_MODE ProfilerMode;
173+
174+
/** Is profiler mode on */
175+
BOOLEAN EnableProfiler;
176+
177+
/** Accelerometer X axis sensitivity increase in percent */
178+
ULONG AccelXSensitivity;
179+
180+
/** Accelerometer Y axis ensitivity increase in percent */
181+
ULONG AccelYSensitivity;
146182

147183
/** True to mute digital pressure buttons */
148184
BOOLEAN MuteDigitalPressureButtons;

sys/DsHidMiniDrv.c

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,74 @@ DMF_DsHidMini_Close(
309309

310310
#pragma endregion
311311

312+
#pragma region Accelerometer Specific
313+
314+
//
315+
// Convert accelerometer values to selected axis
316+
// SHORT value, value to convert
317+
// int mode, what operations to apply
318+
// int sensitivity, sensitivity adjustment value
319+
//
320+
// AccelY converts with wrong tilt for thumb axis so flip, dont break
321+
// AccelY and X gets sensitivity adjustment then add 127 to represent Thumb axis
322+
// Check Y is less than 0 if so make sensitivity adjustment on positive value of Y then double to scale properly
323+
// Check Y is more than 0 if so make sensitivity adjustment on value of Y then double to scale properly
324+
//
325+
//
326+
USHORT AccelConversion(SHORT value,int mode,int sensitivity)
327+
{
328+
switch (mode)
329+
{
330+
case (DsAccelY):
331+
value -= value * 2;
332+
case (DsAccelX):
333+
value = (value * 0XC) / (1000 / sensitivity) + 0X7F;
334+
break;
335+
case (DsAccelYtoL2):
336+
value = (value > 0) ? 0 : (SHORT)abs((value * 0XC) / (1000 / sensitivity) * 2);
337+
break;
338+
case (DsAccelYtoR2):
339+
value = (value < 0) ? 0 : (value * 0XC) / (1000 / sensitivity) * 2;
340+
break;
341+
default:
342+
break;
343+
}
344+
// Ensure in range when returning
345+
return (value < 0) ? 0 : (value = (value > 255) ? 255 : value);
346+
}
347+
348+
//
349+
// Switch profiler mode then perform operations
350+
// takes full inReport and Context currenty
351+
// Y axis Middle/Level seems to need 0X1FF, any less and the reading is offset towards down
352+
// X axis Middle/Level is 0X1F7
353+
// if new L2 or R2 pressure values are above 0 set as engaged
354+
//
355+
356+
PDS3_RAW_INPUT_REPORT AccelProfiler(PDS3_RAW_INPUT_REPORT pInReport, PDEVICE_CONTEXT pDevCtx)
357+
{
358+
359+
switch (pDevCtx->Configuration.ProfilerMode)
360+
{
361+
case DsProfileModeb:
362+
pInReport->LeftThumbY = (UCHAR)AccelConversion(0X1FF - _byteswap_ushort(pInReport->AccelerometerY), DsAccelY, pDevCtx->Configuration.AccelYSensitivity);
363+
case DsProfileModea:
364+
pInReport->LeftThumbX = (UCHAR)AccelConversion(0X1F7 - _byteswap_ushort(pInReport->AccelerometerX), DsAccelX, pDevCtx->Configuration.AccelXSensitivity);
365+
break;
366+
case DsProfileModec:
367+
pInReport->LeftThumbX = (UCHAR)AccelConversion(0X1F7 - _byteswap_ushort(pInReport->AccelerometerX), DsAccelX, pDevCtx->Configuration.AccelXSensitivity);
368+
pInReport->Pressure.Values.R2 = (UCHAR)AccelConversion(0X1FF - _byteswap_ushort(pInReport->AccelerometerY), DsAccelYtoR2, pDevCtx->Configuration.AccelYSensitivity);
369+
if (pInReport->Pressure.Values.R2) { pInReport->Buttons.Individual.R2 = 1; }
370+
pInReport->Pressure.Values.L2 = (UCHAR)AccelConversion(0X1FF - _byteswap_ushort(pInReport->AccelerometerY), DsAccelYtoL2, pDevCtx->Configuration.AccelYSensitivity);
371+
if (pInReport->Pressure.Values.L2) { pInReport->Buttons.Individual.L2 = 1; }
372+
default:
373+
break;
374+
}
375+
return pInReport;
376+
}
377+
378+
#pragma endregion
379+
312380
#pragma region DMF Virtual HID Mini-specific
313381

314382
NTSTATUS
@@ -1483,6 +1551,42 @@ VOID DsUsb_EvtUsbInterruptPipeReadComplete(
14831551
{
14841552
pDevCtx->BatteryStatus = battery;
14851553
}
1554+
1555+
//
1556+
// Quick profile combo (L1 + (Circle || Cross || Triangle || Square)) detectection
1557+
//
1558+
if (pDevCtx->Configuration.EnableProfiler && pInReport->Buttons.Individual.PS)
1559+
{
1560+
t1 = &pDevCtx->ProfileSwitcherTimestamp;
1561+
1562+
if (pDevCtx->ProfileSwitcherTimestamp.QuadPart == 0)
1563+
{
1564+
QueryPerformanceCounter(t1);
1565+
}
1566+
1567+
QueryPerformanceCounter(&t2);
1568+
1569+
ms = (t2.QuadPart - t1->QuadPart) / (freq.QuadPart / 1000);
1570+
1571+
//
1572+
// Timeout reached so check if mode change is requested
1573+
//
1574+
if (ms > 1000)
1575+
{
1576+
DS_PROFILE_MODE mode = (pInReport->Buttons.Individual.Cross) ? DsProfileModeDefault :
1577+
(pInReport->Buttons.Individual.Square) ? DsProfileModea :
1578+
(pInReport->Buttons.Individual.Triangle) ? DsProfileModeb :
1579+
(pInReport->Buttons.Individual.Circle) ? DsProfileModec : -1;
1580+
pDevCtx->Configuration.ProfilerMode = ((mode > -1) && (pDevCtx->Configuration.ProfilerMode != mode)) ? mode : pDevCtx->Configuration.ProfilerMode;
1581+
FuncExitNoReturn(TRACE_DSHIDMINIDRV);
1582+
return;
1583+
}
1584+
}
1585+
1586+
//
1587+
// If not default profile process accelerometer data for pInReport
1588+
//
1589+
pInReport = (pDevCtx->Configuration.EnableProfiler && (pDevCtx->Configuration.ProfilerMode != DsProfileModeDefault)) ? AccelProfiler(pInReport, pDevCtx) : pInReport;
14861590

14871591
Ds_ProcessHidInputReport(pDevCtx, pInReport);
14881592

@@ -1798,6 +1902,41 @@ DsBth_HidInterruptReadContinuousRequestCompleted(
17981902
pDevCtx->Connection.Bth.IdleDisconnectTimestamp.QuadPart = 0;
17991903
}
18001904

1905+
//
1906+
// Quick profile combo (L1 + (Circle || Cross || Triangle || Square)) detectection
1907+
//
1908+
if (pDevCtx->Configuration.EnableProfiler && pInReport->Buttons.Individual.PS)
1909+
{
1910+
t1 = &pDevCtx->ProfileSwitcherTimestamp;
1911+
1912+
if (pDevCtx->ProfileSwitcherTimestamp.QuadPart == 0)
1913+
{
1914+
QueryPerformanceCounter(t1);
1915+
}
1916+
1917+
QueryPerformanceCounter(&t2);
1918+
1919+
ms = (t2.QuadPart - t1->QuadPart) / (freq.QuadPart / 1000);
1920+
1921+
//
1922+
// Timeout reached so check if mode change is requested
1923+
//
1924+
if (ms > 1000)
1925+
{
1926+
DS_PROFILE_MODE mode = (pInReport->Buttons.Individual.Cross) ? DsProfileModeDefault :
1927+
(pInReport->Buttons.Individual.Square) ? DsProfileModea :
1928+
(pInReport->Buttons.Individual.Triangle) ? DsProfileModeb :
1929+
(pInReport->Buttons.Individual.Circle) ? DsProfileModec : -1;
1930+
pDevCtx->Configuration.ProfilerMode = ((mode > -1) && (pDevCtx->Configuration.ProfilerMode != mode)) ? mode : pDevCtx->Configuration.ProfilerMode;
1931+
}
1932+
return ContinuousRequestTarget_BufferDisposition_ContinuousRequestTargetAndContinueStreaming;
1933+
}
1934+
1935+
//
1936+
// If not default profile process accelerometer data for pInReport
1937+
//
1938+
pInReport = (pDevCtx->Configuration.EnableProfiler && (pDevCtx->Configuration.ProfilerMode != DsProfileModeDefault)) ? AccelProfiler(pInReport, pDevCtx) : pInReport;
1939+
18011940
Ds_ProcessHidInputReport(pDevCtx, pInReport);
18021941

18031942
return ContinuousRequestTarget_BufferDisposition_ContinuousRequestTargetAndContinueStreaming;

sys/dshmguid.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,16 @@ DEFINE_DEVPROPKEY(DEVPKEY_DsHidMini_RW_WirelessIdleTimeoutPeriodMs,
7373
DEFINE_DEVPROPKEY(DEVPKEY_DsHidMini_HR_MuteDigitalPressureButtons,
7474
0x99accb6c, 0xd709, 0x49bb, 0x90, 0xee, 0x27, 0x8b, 0x1b, 0x56, 0x4a, 0x4b, 2); // DEVPROP_TYPE_BYTE
7575

76+
// {99ACCB6C-D709-49BB-90EE-278B1B564A4B}
77+
DEFINE_DEVPROPKEY(DEVPKEY_DsHidMini_HR_EnableProfiler,
78+
0x99accb6c, 0xd709, 0x49bb, 0x90, 0xee, 0x27, 0x8b, 0x1b, 0x56, 0x4a, 0x4b, 3); // DEVPROP_TYPE_BYTE
79+
80+
// {99ACCB6C-D709-49BB-90EE-278B1B564A4B}
81+
DEFINE_DEVPROPKEY(DEVPKEY_DsHidMini_HR_AccelXSensitivity,
82+
0x99accb6c, 0xd709, 0x49bb, 0x90, 0xee, 0x27, 0x8b, 0x1b, 0x56, 0x4a, 0x4b, 4); // DEVPROP_TYPE_UINT32
83+
84+
// {99ACCB6C-D709-49BB-90EE-278B1B564A4B}
85+
DEFINE_DEVPROPKEY(DEVPKEY_DsHidMini_HR_AccelYSensitivity,
86+
0x99accb6c, 0xd709, 0x49bb, 0x90, 0xee, 0x27, 0x8b, 0x1b, 0x56, 0x4a, 0x4b, 5); // DEVPROP_TYPE_UINT32
87+
7688
#pragma endregion

0 commit comments

Comments
 (0)