diff options
author | Kim Low <kim-huei.low@sony.com> | 2018-11-09 17:15:13 -0800 |
---|---|---|
committer | Kim Low <kim-huei.low@sony.com> | 2018-12-06 09:35:27 -0800 |
commit | d47c0131eb61989801003251fcb41f99ebbee716 (patch) | |
tree | 20ba2758d13fff0e2a320a17e22b40f804e8690e /cmds/hid/src | |
parent | c3d4693f7993af6f7f9c5068ff63e3970fa0c860 (diff) |
Add support for UHID_GET_REPORT requests
Updated to support UHID_GET_REPORT requests mainly for CTS use.
All feature reports are assumed to be static and should be specified
along with the register json.
For example, in sony_dualshock4_register.json, add the following.
"feature_reports": [
{
"id": 5,
"data": [0x05, 0x1e, 0x00, 0x05, 0x00, 0xe2, 0xff, 0xf2, 0x22, 0xbe, 0x22, 0x8d, 0x22, 0x4f,
0xdd, 0x4d, 0xdd, 0x39, 0xdd, 0x1c, 0x02, 0x1c, 0x02, 0xe3, 0x1f, 0x8b, 0xdf, 0x8c, 0x1e,
0xb4, 0xde, 0x30, 0x20, 0x71, 0xe0, 0x10, 0x00, 0xca, 0xfc, 0x64, 0x4d]
}
]
Test: Make sure build has hid-sony driver that's backported from >4.10.
Run Dualshock4 CTS
> atest cts/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4TestCase.java
Change-Id: Ib0d534d47c6aa6fcc11af68b913c3db1cfa72752
Diffstat (limited to 'cmds/hid/src')
-rw-r--r-- | cmds/hid/src/com/android/commands/hid/Device.java | 35 | ||||
-rw-r--r-- | cmds/hid/src/com/android/commands/hid/Event.java | 55 | ||||
-rw-r--r-- | cmds/hid/src/com/android/commands/hid/Hid.java | 2 |
3 files changed, 89 insertions, 3 deletions
diff --git a/cmds/hid/src/com/android/commands/hid/Device.java b/cmds/hid/src/com/android/commands/hid/Device.java index 8c52a8ed1e09..616d411ef7bb 100644 --- a/cmds/hid/src/com/android/commands/hid/Device.java +++ b/cmds/hid/src/com/android/commands/hid/Device.java @@ -23,6 +23,7 @@ import android.os.Message; import android.os.MessageQueue; import android.os.SystemClock; import android.util.Log; +import android.util.SparseArray; import com.android.internal.os.SomeArgs; @@ -31,11 +32,14 @@ public class Device { private static final int MSG_OPEN_DEVICE = 1; private static final int MSG_SEND_REPORT = 2; - private static final int MSG_CLOSE_DEVICE = 3; + private static final int MSG_SEND_GET_FEATURE_REPORT_REPLY = 3; + private static final int MSG_CLOSE_DEVICE = 4; private final int mId; private final HandlerThread mThread; private final DeviceHandler mHandler; + // mFeatureReports is limited to 256 entries, because the report number is 8-bit + private final SparseArray<byte[]> mFeatureReports; private long mTimeToSend; private final Object mCond = new Object(); @@ -47,13 +51,16 @@ public class Device { private static native long nativeOpenDevice(String name, int id, int vid, int pid, byte[] descriptor, DeviceCallback callback); private static native void nativeSendReport(long ptr, byte[] data); + private static native void nativeSendGetFeatureReportReply(long ptr, int id, byte[] data); private static native void nativeCloseDevice(long ptr); - public Device(int id, String name, int vid, int pid, byte[] descriptor, byte[] report) { + public Device(int id, String name, int vid, int pid, byte[] descriptor, + byte[] report, SparseArray<byte[]> featureReports) { mId = id; mThread = new HandlerThread("HidDeviceHandler"); mThread.start(); mHandler = new DeviceHandler(mThread.getLooper()); + mFeatureReports = featureReports; SomeArgs args = SomeArgs.obtain(); args.argi1 = id; args.argi2 = vid; @@ -113,6 +120,13 @@ public class Device { Log.e(TAG, "Tried to send report to closed device."); } break; + case MSG_SEND_GET_FEATURE_REPORT_REPLY: + if (mPtr != 0) { + nativeSendGetFeatureReportReply(mPtr, msg.arg1, (byte[]) msg.obj); + } else { + Log.e(TAG, "Tried to send feature report reply to closed device."); + } + break; case MSG_CLOSE_DEVICE: if (mPtr != 0) { nativeCloseDevice(mPtr); @@ -145,6 +159,23 @@ public class Device { mHandler.resumeEvents(); } + public void onDeviceGetReport(int requestId, int reportId) { + byte[] report = mFeatureReports.get(reportId); + + if (report == null) { + Log.e(TAG, "Requested feature report " + reportId + " is not specified"); + } + + Message msg; + msg = mHandler.obtainMessage(MSG_SEND_GET_FEATURE_REPORT_REPLY, requestId, 0, report); + + // Message is set to asynchronous so it won't be blocked by synchronization + // barrier during UHID_OPEN. This is necessary for drivers that do + // UHID_GET_REPORT requests during probe. + msg.setAsynchronous(true); + mHandler.sendMessageAtTime(msg, mTimeToSend); + } + public void onDeviceError() { Log.e(TAG, "Device error occurred, closing /dev/uhid"); Message msg = mHandler.obtainMessage(MSG_CLOSE_DEVICE); diff --git a/cmds/hid/src/com/android/commands/hid/Event.java b/cmds/hid/src/com/android/commands/hid/Event.java index c6a37bd3c48f..746e37289076 100644 --- a/cmds/hid/src/com/android/commands/hid/Event.java +++ b/cmds/hid/src/com/android/commands/hid/Event.java @@ -19,6 +19,7 @@ package com.android.commands.hid; import android.util.JsonReader; import android.util.JsonToken; import android.util.Log; +import android.util.SparseArray; import java.io.InputStreamReader; import java.io.IOException; @@ -39,6 +40,7 @@ public class Event { private int mVid; private int mPid; private byte[] mReport; + private SparseArray<byte[]> mFeatureReports; private int mDuration; public int getId() { @@ -69,6 +71,10 @@ public class Event { return mReport; } + public SparseArray<byte[]> getFeatureReports() { + return mFeatureReports; + } + public int getDuration() { return mDuration; } @@ -81,6 +87,7 @@ public class Event { + ", vid=" + mVid + ", pid=" + mPid + ", report=" + Arrays.toString(mReport) + + ", feature_reports=" + mFeatureReports.toString() + ", duration=" + mDuration + "}"; } @@ -112,6 +119,10 @@ public class Event { mEvent.mReport = report; } + public void setFeatureReports(SparseArray<byte[]> reports) { + mEvent.mFeatureReports = reports; + } + public void setVid(int vid) { mEvent.mVid = vid; } @@ -185,6 +196,9 @@ public class Event { case "report": eb.setReport(readData()); break; + case "feature_reports": + eb.setFeatureReports(readFeatureReports()); + break; case "duration": eb.setDuration(readInt()); break; @@ -234,6 +248,47 @@ public class Event { return Integer.decode(val); } + private SparseArray<byte[]> readFeatureReports() + throws IllegalStateException, IOException { + SparseArray<byte[]> featureReports = new SparseArray(); + try { + mReader.beginArray(); + while (mReader.hasNext()) { + // If "id" is not specified, it defaults to 0, which means + // report does not contain report ID (based on HID specs). + int id = 0; + byte[] data = null; + mReader.beginObject(); + while (mReader.hasNext()) { + String name = mReader.nextName(); + switch (name) { + case "id": + id = readInt(); + break; + case "data": + data = readData(); + break; + default: + consumeRemainingElements(); + mReader.endObject(); + throw new IllegalStateException("Invalid key in feature report: " + + name); + } + } + mReader.endObject(); + if (data != null) + featureReports.put(id, data); + } + mReader.endArray(); + } catch (IllegalStateException|NumberFormatException e) { + consumeRemainingElements(); + mReader.endArray(); + throw new IllegalStateException("Encountered malformed data.", e); + } finally { + return featureReports; + } + } + private void consumeRemainingElements() throws IOException { while (mReader.hasNext()) { mReader.skipValue(); diff --git a/cmds/hid/src/com/android/commands/hid/Hid.java b/cmds/hid/src/com/android/commands/hid/Hid.java index 234e47f12dee..54ac1b0733ff 100644 --- a/cmds/hid/src/com/android/commands/hid/Hid.java +++ b/cmds/hid/src/com/android/commands/hid/Hid.java @@ -119,7 +119,7 @@ public class Hid { } int id = e.getId(); Device d = new Device(id, e.getName(), e.getVendorId(), e.getProductId(), - e.getDescriptor(), e.getReport()); + e.getDescriptor(), e.getReport(), e.getFeatureReports()); mDevices.append(id, d); } |