Added Android hidapi 0.14.0 support

main
Sam Lantinga 2023-05-24 18:08:34 -07:00
parent 92b3969ea3
commit bb12c6e03e
6 changed files with 1566 additions and 94 deletions

View File

@ -13,9 +13,8 @@ interface HIDDevice
public String getProductName(); public String getProductName();
public UsbDevice getDevice(); public UsbDevice getDevice();
public boolean open(); public boolean open();
public int sendFeatureReport(byte[] report); public int writeReport(byte[] report, boolean feature);
public int sendOutputReport(byte[] report); public boolean readReport(byte[] report, boolean feature);
public boolean getFeatureReport(byte[] report);
public void setFrozen(boolean frozen); public void setFrozen(boolean frozen);
public void close(); public void close();
public void shutdown(); public void shutdown();

View File

@ -457,7 +457,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
//Log.v(TAG, "onCharacteristicRead status=" + status + " uuid=" + characteristic.getUuid()); //Log.v(TAG, "onCharacteristicRead status=" + status + " uuid=" + characteristic.getUuid());
if (characteristic.getUuid().equals(reportCharacteristic) && !mFrozen) { if (characteristic.getUuid().equals(reportCharacteristic) && !mFrozen) {
mManager.HIDDeviceFeatureReport(getId(), characteristic.getValue()); mManager.HIDDeviceReportResponse(getId(), characteristic.getValue());
} }
finishCurrentGattOperation(); finishCurrentGattOperation();
@ -575,50 +575,45 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
} }
@Override @Override
public int sendFeatureReport(byte[] report) { public int writeReport(byte[] report, boolean feature) {
if (!isRegistered()) { if (!isRegistered()) {
Log.e(TAG, "Attempted sendFeatureReport before Steam Controller is registered!"); Log.e(TAG, "Attempted writeReport before Steam Controller is registered!");
if (mIsConnected) { if (mIsConnected) {
probeService(this); probeService(this);
} }
return -1; return -1;
} }
// We need to skip the first byte, as that doesn't go over the air if (feature) {
byte[] actual_report = Arrays.copyOfRange(report, 1, report.length - 1); // We need to skip the first byte, as that doesn't go over the air
//Log.v(TAG, "sendFeatureReport " + HexDump.dumpHexString(actual_report)); byte[] actual_report = Arrays.copyOfRange(report, 1, report.length - 1);
writeCharacteristic(reportCharacteristic, actual_report); //Log.v(TAG, "writeFeatureReport " + HexDump.dumpHexString(actual_report));
return report.length; writeCharacteristic(reportCharacteristic, actual_report);
} return report.length;
} else {
@Override //Log.v(TAG, "writeOutputReport " + HexDump.dumpHexString(report));
public int sendOutputReport(byte[] report) { writeCharacteristic(reportCharacteristic, report);
if (!isRegistered()) { return report.length;
Log.e(TAG, "Attempted sendOutputReport before Steam Controller is registered!");
if (mIsConnected) {
probeService(this);
}
return -1;
} }
//Log.v(TAG, "sendFeatureReport " + HexDump.dumpHexString(report));
writeCharacteristic(reportCharacteristic, report);
return report.length;
} }
@Override @Override
public boolean getFeatureReport(byte[] report) { public boolean readReport(byte[] report, boolean feature) {
if (!isRegistered()) { if (!isRegistered()) {
Log.e(TAG, "Attempted getFeatureReport before Steam Controller is registered!"); Log.e(TAG, "Attempted readReport before Steam Controller is registered!");
if (mIsConnected) { if (mIsConnected) {
probeService(this); probeService(this);
} }
return false; return false;
} }
//Log.v(TAG, "getFeatureReport"); if (feature) {
readCharacteristic(reportCharacteristic); readCharacteristic(reportCharacteristic);
return true; return true;
} else {
// Not implemented
return false;
}
} }
@Override @Override

View File

@ -599,9 +599,9 @@ public class HIDDeviceManager {
return false; return false;
} }
public int sendOutputReport(int deviceID, byte[] report) { public int writeReport(int deviceID, byte[] report, boolean feature) {
try { try {
//Log.v(TAG, "sendOutputReport deviceID=" + deviceID + " length=" + report.length); //Log.v(TAG, "writeReport deviceID=" + deviceID + " length=" + report.length);
HIDDevice device; HIDDevice device;
device = getDevice(deviceID); device = getDevice(deviceID);
if (device == null) { if (device == null) {
@ -609,33 +609,16 @@ public class HIDDeviceManager {
return -1; return -1;
} }
return device.sendOutputReport(report); return device.writeReport(report, feature);
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e)); Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
} }
return -1; return -1;
} }
public int sendFeatureReport(int deviceID, byte[] report) { public boolean readReport(int deviceID, byte[] report, boolean feature) {
try { try {
//Log.v(TAG, "sendFeatureReport deviceID=" + deviceID + " length=" + report.length); //Log.v(TAG, "readReport deviceID=" + deviceID);
HIDDevice device;
device = getDevice(deviceID);
if (device == null) {
HIDDeviceDisconnected(deviceID);
return -1;
}
return device.sendFeatureReport(report);
} catch (Exception e) {
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
}
return -1;
}
public boolean getFeatureReport(int deviceID, byte[] report) {
try {
//Log.v(TAG, "getFeatureReport deviceID=" + deviceID);
HIDDevice device; HIDDevice device;
device = getDevice(deviceID); device = getDevice(deviceID);
if (device == null) { if (device == null) {
@ -643,7 +626,7 @@ public class HIDDeviceManager {
return false; return false;
} }
return device.getFeatureReport(report); return device.readReport(report, feature);
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e)); Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
} }
@ -680,5 +663,5 @@ public class HIDDeviceManager {
native void HIDDeviceDisconnected(int deviceID); native void HIDDeviceDisconnected(int deviceID);
native void HIDDeviceInputReport(int deviceID, byte[] report); native void HIDDeviceInputReport(int deviceID, byte[] report);
native void HIDDeviceFeatureReport(int deviceID, byte[] report); native void HIDDeviceReportResponse(int deviceID, byte[] report);
} }

View File

@ -153,49 +153,48 @@ class HIDDeviceUSB implements HIDDevice {
} }
@Override @Override
public int sendFeatureReport(byte[] report) { public int writeReport(byte[] report, boolean feature) {
int res = -1; if (feature) {
int offset = 0; int res = -1;
int length = report.length; int offset = 0;
boolean skipped_report_id = false; int length = report.length;
byte report_number = report[0]; boolean skipped_report_id = false;
byte report_number = report[0];
if (report_number == 0x0) { if (report_number == 0x0) {
++offset; ++offset;
--length; --length;
skipped_report_id = true; skipped_report_id = true;
}
res = mConnection.controlTransfer(
UsbConstants.USB_TYPE_CLASS | 0x01 /*RECIPIENT_INTERFACE*/ | UsbConstants.USB_DIR_OUT,
0x09/*HID set_report*/,
(3/*HID feature*/ << 8) | report_number,
mInterface,
report, offset, length,
1000/*timeout millis*/);
if (res < 0) {
Log.w(TAG, "writeFeatureReport() returned " + res + " on device " + getDeviceName());
return -1;
}
if (skipped_report_id) {
++length;
}
return length;
} else {
int res = mConnection.bulkTransfer(mOutputEndpoint, report, report.length, 1000);
if (res != report.length) {
Log.w(TAG, "writeOutputReport() returned " + res + " on device " + getDeviceName());
}
return res;
} }
res = mConnection.controlTransfer(
UsbConstants.USB_TYPE_CLASS | 0x01 /*RECIPIENT_INTERFACE*/ | UsbConstants.USB_DIR_OUT,
0x09/*HID set_report*/,
(3/*HID feature*/ << 8) | report_number,
mInterface,
report, offset, length,
1000/*timeout millis*/);
if (res < 0) {
Log.w(TAG, "sendFeatureReport() returned " + res + " on device " + getDeviceName());
return -1;
}
if (skipped_report_id) {
++length;
}
return length;
} }
@Override @Override
public int sendOutputReport(byte[] report) { public boolean readReport(byte[] report, boolean feature) {
int r = mConnection.bulkTransfer(mOutputEndpoint, report, report.length, 1000);
if (r != report.length) {
Log.w(TAG, "sendOutputReport() returned " + r + " on device " + getDeviceName());
}
return r;
}
@Override
public boolean getFeatureReport(byte[] report) {
int res = -1; int res = -1;
int offset = 0; int offset = 0;
int length = report.length; int length = report.length;
@ -213,7 +212,7 @@ class HIDDeviceUSB implements HIDDevice {
res = mConnection.controlTransfer( res = mConnection.controlTransfer(
UsbConstants.USB_TYPE_CLASS | 0x01 /*RECIPIENT_INTERFACE*/ | UsbConstants.USB_DIR_IN, UsbConstants.USB_TYPE_CLASS | 0x01 /*RECIPIENT_INTERFACE*/ | UsbConstants.USB_DIR_IN,
0x01/*HID get_report*/, 0x01/*HID get_report*/,
(3/*HID feature*/ << 8) | report_number, ((feature ? 3/*HID feature*/ : 1/*HID Input*/) << 8) | report_number,
mInterface, mInterface,
report, offset, length, report, offset, length,
1000/*timeout millis*/); 1000/*timeout millis*/);
@ -234,7 +233,7 @@ class HIDDeviceUSB implements HIDDevice {
} else { } else {
data = Arrays.copyOfRange(report, 0, res); data = Arrays.copyOfRange(report, 0, res);
} }
mManager.HIDDeviceFeatureReport(mDeviceId, data); mManager.HIDDeviceReportResponse(mDeviceId, data);
return true; return true;
} }

1457
src/hidapi/android/hid.cpp Normal file

File diff suppressed because it is too large Load Diff

39
src/hidapi/android/hid.h Normal file
View File

@ -0,0 +1,39 @@
/*
Simple DirectMedia Layer
Copyright (C) 2022 Valve Corporation
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
// Purpose: Exporting table containing HIDDeviceManager native methods
#ifndef SDL_android_hid_h_
#define SDL_android_hid_h_
#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
extern JNINativeMethod HIDDeviceManager_tab[8];
#ifdef __cplusplus
}
#endif
#endif