Skip to content

Commit

Permalink
Closes #8 - Switch from Pure Java HID-API to hid4java
Browse files Browse the repository at this point in the history
  • Loading branch information
bwRavencl committed Apr 3, 2023
1 parent bf8cde3 commit ee6271b
Show file tree
Hide file tree
Showing 5 changed files with 419 additions and 451 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,11 @@ ControllerBuddy uses the following awesome software technologies and libraries:
- [ClassGraph](https://github.com/classgraph/classgraph)
- [FlatLaf](https://www.formdev.com/flatlaf/)
- [Gson](https://github.com/google/gson)
- [hid4java](https://github.com/gary-rowe/hid4java)
- [Java Native Access (JNA)](https://github.com/java-native-access/jna)
- [JXInput](https://github.com/StrikerX3/JXInput)
- [linuxio4j](https://github.com/bithatch/linuxio4j)
- [LWJGL - Lightweight Java Game Library 3](https://www.lwjgl.org)
- [Pure Java HID-API](https://github.com/nyholku/purejavahidapi)
- [SDL_GameControllerDB](https://github.com/gabomdq/SDL_GameControllerDB)
#### Building:
Expand Down
11 changes: 5 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ ext {
batikVersion = '1.16'
commonsCliVersion = '1.5.0'
jxinputVersion = '1.0.0'
purejavahidapiVersion = 'ef5679619d'
hid4javaVersion = '85d76ecd85'

openVrSupport = false
}
Expand Down Expand Up @@ -147,9 +147,8 @@ dependencies {
"org.lwjgl:lwjgl-openvr:$lwjglVersion",
"org.lwjgl:lwjgl:$lwjglVersion:natives-$lwjglPlatform"

implementation("com.github.nyholku:purejavahidapi:$purejavahidapiVersion") {
implementation("com.github.gary-rowe:hid4java:$hid4javaVersion") {
exclude module: 'jna'
exclude module: 'jna-platform'
}

implementation('uk.co.bithatch:linuxio4j:2.1') {
Expand All @@ -169,7 +168,7 @@ dependencies {
dependencyUpdates {
revision = 'release'
rejectVersionIf {
it.candidate.module in ['purejavahidapi']
it.candidate.module in ['hid4java']
}
}

Expand All @@ -195,7 +194,7 @@ extraJavaModuleInfo {
automaticModule('commons-io-1.3.1.jar', 'commons.io')
automaticModule('commons-logging-1.0.4.jar', 'commons.logging')
automaticModule("jxinput-${jxinputVersion}.jar", 'jxinput')
automaticModule("purejavahidapi-${purejavahidapiVersion}.jar", 'purejavahidapi')
automaticModule("hid4java-${hid4javaVersion}.jar", 'hid4java')
automaticModule('xmlgraphics-commons-2.7.jar', 'xml.graphics.commons')
automaticModule('xml-apis-ext-1.3.04.jar', 'xml.apis.ext')

Expand Down Expand Up @@ -247,6 +246,7 @@ task generateModuleInfo {
\trequires com.sun.jna;
\trequires com.sun.jna.platform;
\trequires commons.cli;
\trequires hid4java;
\trequires io.github.classgraph;
\trequires java.logging;
\trequires java.prefs;
Expand All @@ -260,7 +260,6 @@ task generateModuleInfo {
${openVrSupport ? '\trequires org.lwjgl.opengl.natives;' : ''}
\trequires org.lwjgl.openvr;
${openVrSupport ? '\trequires org.lwjgl.openvr.natives;' : ''}
\trequires purejavahidapi;
\trequires uk.co.bithatch.linuxio;
}
""".stripIndent())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,18 @@

package de.bwravencl.controllerbuddy.input.driver.sony;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.hid4java.HidDevice;
import org.lwjgl.glfw.GLFW;

import de.bwravencl.controllerbuddy.gui.Main;
import de.bwravencl.controllerbuddy.gui.Main.ControllerInfo;
import de.bwravencl.controllerbuddy.input.Input;
import de.bwravencl.controllerbuddy.input.driver.Driver;
import de.bwravencl.controllerbuddy.input.driver.IDriverBuilder;
import purejavahidapi.HidDeviceInfo;
import purejavahidapi.PureJavaHidApi;

public final class DualSenseDriver extends SonyDriver {

Expand All @@ -48,14 +45,10 @@ public Driver getIfAvailable(final Input input, final List<ControllerInfo> prese
if (!"PS5 Controller".equals(name))
return null;

final var hidDeviceInfo = getHidDeviceInfo(presentControllers, selectedController, (short) 0xCE6,
"DualSense", log);
if (hidDeviceInfo != null)
try {
return new DualSenseDriver(input, selectedController, hidDeviceInfo);
} catch (final IOException e) {
log.log(Level.SEVERE, e.getMessage(), e);
}
final var hidDevice = getHidDevice(presentControllers, selectedController, (short) 0xCE6, "DualSense", log);

if (hidDevice != null)
return new DualSenseDriver(input, selectedController, hidDevice);

return null;
}
Expand All @@ -69,52 +62,8 @@ public Driver getIfAvailable(final Input input, final List<ControllerInfo> prese
private static final Connection UsbConnection = new Connection(0, USB_INPUT_REPORT_ID);
private static final Connection BluetoothConnection = new Connection(1, BLUETOOTH_INPUT_REPORT_ID);

private DualSenseDriver(final Input input, final ControllerInfo controller, final HidDeviceInfo hidDeviceInfo)
throws IOException {
super(input, controller);

try {
hidDevice = PureJavaHidApi.openDevice(hidDeviceInfo);

hidDevice.setInputReportListener(new SonyInputReportListener() {

@Override
void handleBattery(final byte[] reportData, final int offset) {
final var chargingStatus = (reportData[53 + offset] & 0xF0) >> 4;
final var batteryData = reportData[53 + offset] & 0xF;

final int batteryCapacity;
final var charging = switch (chargingStatus) {
case 0x0 -> {
batteryCapacity = batteryData == 10 ? 100 : batteryData * 10 + 5;
yield false;
}
case 0x1 -> {
batteryCapacity = batteryData == 10 ? 100 : batteryData * 10 + 5;
yield true;
}
case 0x2 -> {
batteryCapacity = 100;
yield false;
}
default -> {
batteryCapacity = 0;
yield false;
}
};
setCharging(charging);
setBatteryCapacity(batteryCapacity);
}

@Override
void handleNewConnection(final int reportLength) {
connection = isBluetoothConnection(reportLength) ? BluetoothConnection : UsbConnection;
}
});
} catch (final Throwable t) {
deInit(false);
throw t;
}
private DualSenseDriver(final Input input, final ControllerInfo controller, final HidDevice hidDevice) {
super(input, controller, hidDevice);
}

@Override
Expand All @@ -129,34 +78,35 @@ byte[] getDefaultHidReport() {

final byte[] defaultHidReport;
if (connection.isBluetooth()) {
defaultHidReport = new byte[BLUETOOTH_REPORT_LENGTH];

defaultHidReport[0] = 0x31;
defaultHidReport[1] = 0x2;
} else {
defaultHidReport = new byte[48];
defaultHidReport = new byte[BLUETOOTH_REPORT_LENGTH - 1];

defaultHidReport[0] = 0x2;
}
} else
defaultHidReport = new byte[47];

defaultHidReport[1 + connection.offset()] = 0x3;
defaultHidReport[2 + connection.offset()] = 0x15;
defaultHidReport[connection.offset()] = 0x3;
defaultHidReport[1 + connection.offset()] = 0x15;

defaultHidReport[44 + connection.offset()] = (byte) 0x0;
defaultHidReport[45 + connection.offset()] = (byte) 0x0;
defaultHidReport[46 + connection.offset()] = (byte) 0x0;
defaultHidReport[47 + connection.offset()] = (byte) 0xFF;
defaultHidReport[46 + connection.offset()] = (byte) 0xFF;

return defaultHidReport;
}

@Override
byte getDefaultHidReportId() {
return connection.isBluetooth() ? (byte) 0x31 : (byte) 0x2;
}

@Override
int getL2Offset() {
return 5;
return 4;
}

@Override
int getLightbarOffset() {
return 45;
return 44;
}

@Override
Expand All @@ -176,7 +126,7 @@ Logger getLogger() {

@Override
int getRumbleOffset() {
return 4;
return 3;
}

@Override
Expand All @@ -191,22 +141,56 @@ byte getStrongRumbleStrength() {

@Override
int getTouchpadOffset() {
return 33;
return 32;
}

@Override
void handleBattery(final byte[] reportData, final int offset) {
final var chargingStatus = (reportData[53 + offset] & 0xF0) >> 4;
final var batteryData = reportData[53 + offset] & 0xF;

final int batteryCapacity;
final var charging = switch (chargingStatus) {
case 0x0 -> {
batteryCapacity = batteryData == 10 ? 100 : batteryData * 10 + 5;
yield false;
}
case 0x1 -> {
batteryCapacity = batteryData == 10 ? 100 : batteryData * 10 + 5;
yield true;
}
case 0x2 -> {
batteryCapacity = 100;
yield false;
}
default -> {
batteryCapacity = 0;
yield false;
}
};
setCharging(charging);
setBatteryCapacity(batteryCapacity);
}

@Override
void handleNewConnection(final int reportLength) {
connection = isBluetoothConnection(reportLength) ? BluetoothConnection : UsbConnection;
}

@Override
void reset() {
boolean reset() {
if (connection == null)
return;
return false;

if (connection.isBluetooth()) {
final var defaultHidReport = getDefaultHidReport();
hidReport = Arrays.copyOf(defaultHidReport, defaultHidReport.length);
hidReport[3] = 0x8;

sendHidReport();
if (!sendHidReport())
return false;
}

super.reset();
return super.reset();
}
}
Loading

0 comments on commit ee6271b

Please sign in to comment.