Loading cmds/hid/jni/com_android_commands_hid_Device.cpp +32 −17 Original line number Diff line number Diff line Loading @@ -18,24 +18,22 @@ #include "com_android_commands_hid_Device.h" #include <linux/uhid.h> #include <android-base/stringprintf.h> #include <android/looper.h> #include <fcntl.h> #include <inttypes.h> #include <unistd.h> #include <cstdio> #include <cstring> #include <memory> #include <android/looper.h> #include <jni.h> #include <linux/uhid.h> #include <log/log.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedLocalRef.h> #include <nativehelper/ScopedPrimitiveArray.h> #include <nativehelper/ScopedUtfChars.h> #include <unistd.h> #include <android-base/stringprintf.h> #include <cstdio> #include <cstring> #include <memory> // Log debug messages about the output. static constexpr bool DEBUG_OUTPUT = false; Loading Loading @@ -109,15 +107,15 @@ void DeviceCallback::onDeviceOpen() { void DeviceCallback::onDeviceGetReport(uint32_t requestId, uint8_t reportId) { JNIEnv* env = getJNIEnv(); env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceGetReport, requestId, reportId); env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceGetReport, requestId, reportId); checkAndClearException(env, "onDeviceGetReport"); } void DeviceCallback::onDeviceSetReport(uint8_t rType, void DeviceCallback::onDeviceSetReport(uint32_t id, uint8_t rType, const std::vector<uint8_t>& data) { JNIEnv* env = getJNIEnv(); env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceSetReport, rType, env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceSetReport, id, rType, toJbyteArray(env, data).get()); checkAndClearException(env, "onDeviceSetReport"); } Loading Loading @@ -236,6 +234,14 @@ void Device::sendGetFeatureReportReply(uint32_t id, const std::vector<uint8_t>& writeEvent(mFd, ev, "UHID_GET_REPORT_REPLY"); } void Device::sendSetReportReply(uint32_t id, bool success) const { struct uhid_event ev = {}; ev.type = UHID_SET_REPORT_REPLY; ev.u.set_report_reply.id = id; ev.u.set_report_reply.err = success ? 0 : EIO; writeEvent(mFd, ev, "UHID_SET_REPORT_REPLY"); } int Device::handleEvents(int events) { if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) { ALOGE("uhid node was closed or an error occurred. events=0x%x", events); Loading @@ -249,7 +255,6 @@ int Device::handleEvents(int events) { mDeviceCallback->onDeviceError(); return 0; } switch (ev.type) { case UHID_OPEN: { mDeviceCallback->onDeviceOpen(); Loading @@ -271,7 +276,7 @@ int Device::handleEvents(int events) { ALOGD("Received SET_REPORT: id=%" PRIu32 " rnum=%" PRIu8 " data=%s", set_report.id, set_report.rnum, toString(data).c_str()); } mDeviceCallback->onDeviceSetReport(set_report.rtype, data); mDeviceCallback->onDeviceSetReport(set_report.id, set_report.rtype, data); break; } case UHID_OUTPUT: { Loading Loading @@ -347,6 +352,15 @@ static void sendGetFeatureReportReply(JNIEnv* env, jclass /* clazz */, jlong ptr } } static void sendSetReportReply(JNIEnv*, jclass /* clazz */, jlong ptr, jint id, jboolean success) { uhid::Device* d = reinterpret_cast<uhid::Device*>(ptr); if (d) { d->sendSetReportReply(id, success); } else { ALOGE("Could not send set report reply, Device* is null!"); } } static void closeDevice(JNIEnv* /* env */, jclass /* clazz */, jlong ptr) { uhid::Device* d = reinterpret_cast<uhid::Device*>(ptr); if (d) { Loading @@ -362,6 +376,7 @@ static JNINativeMethod sMethods[] = { {"nativeSendReport", "(J[B)V", reinterpret_cast<void*>(sendReport)}, {"nativeSendGetFeatureReportReply", "(JI[B)V", reinterpret_cast<void*>(sendGetFeatureReportReply)}, {"nativeSendSetReportReply", "(JIZ)V", reinterpret_cast<void*>(sendSetReportReply)}, {"nativeCloseDevice", "(J)V", reinterpret_cast<void*>(closeDevice)}, }; Loading @@ -376,7 +391,7 @@ int register_com_android_commands_hid_Device(JNIEnv* env) { uhid::gDeviceCallbackClassInfo.onDeviceGetReport = env->GetMethodID(clazz, "onDeviceGetReport", "(II)V"); uhid::gDeviceCallbackClassInfo.onDeviceSetReport = env->GetMethodID(clazz, "onDeviceSetReport", "(B[B)V"); env->GetMethodID(clazz, "onDeviceSetReport", "(IB[B)V"); uhid::gDeviceCallbackClassInfo.onDeviceOutput = env->GetMethodID(clazz, "onDeviceOutput", "(B[B)V"); uhid::gDeviceCallbackClassInfo.onDeviceError = Loading cmds/hid/jni/com_android_commands_hid_Device.h +5 −6 Original line number Diff line number Diff line Loading @@ -14,12 +14,11 @@ * limitations under the License. */ #include <memory> #include <vector> #include <android-base/unique_fd.h> #include <jni.h> #include <android-base/unique_fd.h> #include <memory> #include <vector> namespace android { namespace uhid { Loading @@ -31,7 +30,7 @@ public: void onDeviceOpen(); void onDeviceGetReport(uint32_t requestId, uint8_t reportId); void onDeviceSetReport(uint8_t rType, const std::vector<uint8_t>& data); void onDeviceSetReport(uint32_t id, uint8_t rType, const std::vector<uint8_t>& data); void onDeviceOutput(uint8_t rType, const std::vector<uint8_t>& data); void onDeviceError(); Loading @@ -50,9 +49,9 @@ public: ~Device(); void sendReport(const std::vector<uint8_t>& report) const; void sendSetReportReply(uint32_t id, bool success) const; void sendGetFeatureReportReply(uint32_t id, const std::vector<uint8_t>& report) const; void close(); int handleEvents(int events); private: Loading cmds/hid/src/com/android/commands/hid/Device.java +73 −15 Original line number Diff line number Diff line Loading @@ -42,7 +42,8 @@ public class Device { private static final int MSG_OPEN_DEVICE = 1; private static final int MSG_SEND_REPORT = 2; private static final int MSG_SEND_GET_FEATURE_REPORT_REPLY = 3; private static final int MSG_CLOSE_DEVICE = 4; private static final int MSG_SEND_SET_REPORT_REPLY = 4; private static final int MSG_CLOSE_DEVICE = 5; // Sync with linux uhid_event_type::UHID_OUTPUT private static final byte UHID_EVENT_TYPE_UHID_OUTPUT = 6; Loading @@ -56,21 +57,45 @@ public class Device { private final Map<ByteBuffer, byte[]> mOutputs; private final OutputStream mOutputStream; private long mTimeToSend; private final Object mCond = new Object(); /** * The report id of the report received in UHID_EVENT_TYPE_SET_REPORT. * Used for SET_REPORT_REPLY. * This field gets overridden each time SET_REPORT is received. */ private int mResponseId; static { System.loadLibrary("hidcommand_jni"); } private static native long nativeOpenDevice(String name, int id, int vid, int pid, int bus, byte[] descriptor, DeviceCallback callback); private static native long nativeOpenDevice( String name, int id, int vid, int pid, int bus, 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 nativeSendSetReportReply(long ptr, int id, boolean success); private static native void nativeCloseDevice(long ptr); public Device(int id, String name, int vid, int pid, int bus, byte[] descriptor, byte[] report, SparseArray<byte[]> featureReports, Map<ByteBuffer, byte[]> outputs) { public Device( int id, String name, int vid, int pid, int bus, byte[] descriptor, byte[] report, SparseArray<byte[]> featureReports, Map<ByteBuffer, byte[]> outputs) { mId = id; mThread = new HandlerThread("HidDeviceHandler"); mThread.start(); Loading Loading @@ -100,6 +125,17 @@ public class Device { mHandler.sendMessageAtTime(msg, mTimeToSend); } public void setGetReportResponse(byte[] report) { mFeatureReports.put(report[0], report); } public void sendSetReportReply(boolean success) { Message msg = mHandler.obtainMessage(MSG_SEND_SET_REPORT_REPLY, mResponseId, success ? 1 : 0); mHandler.sendMessageAtTime(msg, mTimeToSend); } public void addDelay(int delay) { mTimeToSend = Math.max(SystemClock.uptimeMillis(), mTimeToSend) + delay; } Loading @@ -111,7 +147,8 @@ public class Device { synchronized (mCond) { mCond.wait(); } } catch (InterruptedException ignore) {} } catch (InterruptedException ignore) { } } private class DeviceHandler extends Handler { Loading @@ -127,8 +164,15 @@ public class Device { switch (msg.what) { case MSG_OPEN_DEVICE: SomeArgs args = (SomeArgs) msg.obj; mPtr = nativeOpenDevice((String) args.arg1, args.argi1, args.argi2, args.argi3, args.argi4, (byte[]) args.arg2, new DeviceCallback()); mPtr = nativeOpenDevice( (String) args.arg1, args.argi1, args.argi2, args.argi3, args.argi4, (byte[]) args.arg2, new DeviceCallback()); pauseEvents(); break; case MSG_SEND_REPORT: Loading @@ -145,6 +189,14 @@ public class Device { Log.e(TAG, "Tried to send feature report reply to closed device."); } break; case MSG_SEND_SET_REPORT_REPLY: if (mPtr != 0) { final boolean success = msg.arg2 == 1; nativeSendSetReportReply(mPtr, msg.arg1, success); } else { Log.e(TAG, "Tried to send set report reply to closed device."); } break; case MSG_CLOSE_DEVICE: if (mPtr != 0) { nativeCloseDevice(mPtr); Loading Loading @@ -173,13 +225,17 @@ public class Device { } private class DeviceCallback { public void onDeviceOpen() { mHandler.resumeEvents(); } public void onDeviceGetReport(int requestId, int reportId) { if (mFeatureReports == null) { Log.e(TAG, "Received GET_REPORT request for reportId=" + reportId Log.e( TAG, "Received GET_REPORT request for reportId=" + reportId + ", but 'feature_reports' section is not found"); return; } Loading Loading @@ -220,14 +276,15 @@ public class Device { } catch (IOException e) { throw new RuntimeException(e); } } // native callback public void onDeviceSetReport(byte rtype, byte[] data) { public void onDeviceSetReport(int id, byte rType, byte[] data) { // Used by sendSetReportReply() mResponseId = id; // We don't need to reply for the SET_REPORT but just send it to HID output for test // verification. sendReportOutput(UHID_EVENT_TYPE_SET_REPORT, rtype, data); sendReportOutput(UHID_EVENT_TYPE_SET_REPORT, rType, data); } // native callback Loading @@ -239,7 +296,8 @@ public class Device { } byte[] response = mOutputs.get(ByteBuffer.wrap(data)); if (response == null) { Log.i(TAG, Log.i( TAG, "Requested response for output " + Arrays.toString(data) + " is not found"); return; } Loading cmds/hid/src/com/android/commands/hid/Event.java +30 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ public class Event { public static final String COMMAND_REGISTER = "register"; public static final String COMMAND_DELAY = "delay"; public static final String COMMAND_REPORT = "report"; public static final String COMMAND_SET_GET_REPORT_RESPONSE = "set_get_report_response"; public static final String COMMAND_SEND_SET_REPORT_REPLY = "send_set_report_reply"; // These constants come from "include/uapi/linux/input.h" in the kernel enum Bus { Loading Loading @@ -62,6 +64,7 @@ public class Event { private SparseArray<byte[]> mFeatureReports; private Map<ByteBuffer, byte[]> mOutputs; private int mDuration; private Boolean mReply; public int getId() { return mId; Loading Loading @@ -107,6 +110,10 @@ public class Event { return mDuration; } public Boolean getReply() { return mReply; } public String toString() { return "Event{id=" + mId + ", command=" + String.valueOf(mCommand) Loading @@ -119,6 +126,7 @@ public class Event { + ", feature_reports=" + mFeatureReports.toString() + ", outputs=" + mOutputs.toString() + ", duration=" + mDuration + ", success=" + mReply.toString() + "}"; } Loading Loading @@ -173,6 +181,10 @@ public class Event { mEvent.mDuration = duration; } public void setReply(boolean success) { mEvent.mReply = success; } public Event build() { if (mEvent.mId == -1) { throw new IllegalStateException("No event id"); Loading @@ -183,6 +195,16 @@ public class Event { if (mEvent.mDescriptor == null) { throw new IllegalStateException("Device registration is missing descriptor"); } } if (COMMAND_SET_GET_REPORT_RESPONSE.equals(mEvent.mCommand)) { if (mEvent.mReport == null) { throw new IllegalStateException("Report command is missing response data"); } } if (COMMAND_SEND_SET_REPORT_REPLY.equals(mEvent.mCommand)) { if (mEvent.mReply == null) { throw new IllegalStateException("Reply command is missing reply"); } } else if (COMMAND_DELAY.equals(mEvent.mCommand)) { if (mEvent.mDuration <= 0) { throw new IllegalStateException("Delay has missing or invalid duration"); Loading Loading @@ -246,6 +268,9 @@ public class Event { case "duration": eb.setDuration(readInt()); break; case "success": eb.setReply(readBool()); break; default: mReader.skipValue(); } Loading Loading @@ -292,6 +317,11 @@ public class Event { return Integer.decode(val); } private boolean readBool() throws IOException { String val = mReader.nextString(); return Boolean.parseBoolean(val); } private Bus readBus() throws IOException { String val = mReader.nextString(); return Bus.valueOf(val.toUpperCase()); Loading cmds/hid/src/com/android/commands/hid/Hid.java +4 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,10 @@ public class Hid { d.addDelay(e.getDuration()); } else if (Event.COMMAND_REPORT.equals(e.getCommand())) { d.sendReport(e.getReport()); } else if (Event.COMMAND_SET_GET_REPORT_RESPONSE.equals(e.getCommand())) { d.setGetReportResponse(e.getReport()); } else if (Event.COMMAND_SEND_SET_REPORT_REPLY.equals(e.getCommand())) { d.sendSetReportReply(e.getReply()); } else { if (Event.COMMAND_REGISTER.equals(e.getCommand())) { error("Device id=" + e.getId() + " is already registered. Ignoring event."); Loading Loading
cmds/hid/jni/com_android_commands_hid_Device.cpp +32 −17 Original line number Diff line number Diff line Loading @@ -18,24 +18,22 @@ #include "com_android_commands_hid_Device.h" #include <linux/uhid.h> #include <android-base/stringprintf.h> #include <android/looper.h> #include <fcntl.h> #include <inttypes.h> #include <unistd.h> #include <cstdio> #include <cstring> #include <memory> #include <android/looper.h> #include <jni.h> #include <linux/uhid.h> #include <log/log.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedLocalRef.h> #include <nativehelper/ScopedPrimitiveArray.h> #include <nativehelper/ScopedUtfChars.h> #include <unistd.h> #include <android-base/stringprintf.h> #include <cstdio> #include <cstring> #include <memory> // Log debug messages about the output. static constexpr bool DEBUG_OUTPUT = false; Loading Loading @@ -109,15 +107,15 @@ void DeviceCallback::onDeviceOpen() { void DeviceCallback::onDeviceGetReport(uint32_t requestId, uint8_t reportId) { JNIEnv* env = getJNIEnv(); env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceGetReport, requestId, reportId); env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceGetReport, requestId, reportId); checkAndClearException(env, "onDeviceGetReport"); } void DeviceCallback::onDeviceSetReport(uint8_t rType, void DeviceCallback::onDeviceSetReport(uint32_t id, uint8_t rType, const std::vector<uint8_t>& data) { JNIEnv* env = getJNIEnv(); env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceSetReport, rType, env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceSetReport, id, rType, toJbyteArray(env, data).get()); checkAndClearException(env, "onDeviceSetReport"); } Loading Loading @@ -236,6 +234,14 @@ void Device::sendGetFeatureReportReply(uint32_t id, const std::vector<uint8_t>& writeEvent(mFd, ev, "UHID_GET_REPORT_REPLY"); } void Device::sendSetReportReply(uint32_t id, bool success) const { struct uhid_event ev = {}; ev.type = UHID_SET_REPORT_REPLY; ev.u.set_report_reply.id = id; ev.u.set_report_reply.err = success ? 0 : EIO; writeEvent(mFd, ev, "UHID_SET_REPORT_REPLY"); } int Device::handleEvents(int events) { if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) { ALOGE("uhid node was closed or an error occurred. events=0x%x", events); Loading @@ -249,7 +255,6 @@ int Device::handleEvents(int events) { mDeviceCallback->onDeviceError(); return 0; } switch (ev.type) { case UHID_OPEN: { mDeviceCallback->onDeviceOpen(); Loading @@ -271,7 +276,7 @@ int Device::handleEvents(int events) { ALOGD("Received SET_REPORT: id=%" PRIu32 " rnum=%" PRIu8 " data=%s", set_report.id, set_report.rnum, toString(data).c_str()); } mDeviceCallback->onDeviceSetReport(set_report.rtype, data); mDeviceCallback->onDeviceSetReport(set_report.id, set_report.rtype, data); break; } case UHID_OUTPUT: { Loading Loading @@ -347,6 +352,15 @@ static void sendGetFeatureReportReply(JNIEnv* env, jclass /* clazz */, jlong ptr } } static void sendSetReportReply(JNIEnv*, jclass /* clazz */, jlong ptr, jint id, jboolean success) { uhid::Device* d = reinterpret_cast<uhid::Device*>(ptr); if (d) { d->sendSetReportReply(id, success); } else { ALOGE("Could not send set report reply, Device* is null!"); } } static void closeDevice(JNIEnv* /* env */, jclass /* clazz */, jlong ptr) { uhid::Device* d = reinterpret_cast<uhid::Device*>(ptr); if (d) { Loading @@ -362,6 +376,7 @@ static JNINativeMethod sMethods[] = { {"nativeSendReport", "(J[B)V", reinterpret_cast<void*>(sendReport)}, {"nativeSendGetFeatureReportReply", "(JI[B)V", reinterpret_cast<void*>(sendGetFeatureReportReply)}, {"nativeSendSetReportReply", "(JIZ)V", reinterpret_cast<void*>(sendSetReportReply)}, {"nativeCloseDevice", "(J)V", reinterpret_cast<void*>(closeDevice)}, }; Loading @@ -376,7 +391,7 @@ int register_com_android_commands_hid_Device(JNIEnv* env) { uhid::gDeviceCallbackClassInfo.onDeviceGetReport = env->GetMethodID(clazz, "onDeviceGetReport", "(II)V"); uhid::gDeviceCallbackClassInfo.onDeviceSetReport = env->GetMethodID(clazz, "onDeviceSetReport", "(B[B)V"); env->GetMethodID(clazz, "onDeviceSetReport", "(IB[B)V"); uhid::gDeviceCallbackClassInfo.onDeviceOutput = env->GetMethodID(clazz, "onDeviceOutput", "(B[B)V"); uhid::gDeviceCallbackClassInfo.onDeviceError = Loading
cmds/hid/jni/com_android_commands_hid_Device.h +5 −6 Original line number Diff line number Diff line Loading @@ -14,12 +14,11 @@ * limitations under the License. */ #include <memory> #include <vector> #include <android-base/unique_fd.h> #include <jni.h> #include <android-base/unique_fd.h> #include <memory> #include <vector> namespace android { namespace uhid { Loading @@ -31,7 +30,7 @@ public: void onDeviceOpen(); void onDeviceGetReport(uint32_t requestId, uint8_t reportId); void onDeviceSetReport(uint8_t rType, const std::vector<uint8_t>& data); void onDeviceSetReport(uint32_t id, uint8_t rType, const std::vector<uint8_t>& data); void onDeviceOutput(uint8_t rType, const std::vector<uint8_t>& data); void onDeviceError(); Loading @@ -50,9 +49,9 @@ public: ~Device(); void sendReport(const std::vector<uint8_t>& report) const; void sendSetReportReply(uint32_t id, bool success) const; void sendGetFeatureReportReply(uint32_t id, const std::vector<uint8_t>& report) const; void close(); int handleEvents(int events); private: Loading
cmds/hid/src/com/android/commands/hid/Device.java +73 −15 Original line number Diff line number Diff line Loading @@ -42,7 +42,8 @@ public class Device { private static final int MSG_OPEN_DEVICE = 1; private static final int MSG_SEND_REPORT = 2; private static final int MSG_SEND_GET_FEATURE_REPORT_REPLY = 3; private static final int MSG_CLOSE_DEVICE = 4; private static final int MSG_SEND_SET_REPORT_REPLY = 4; private static final int MSG_CLOSE_DEVICE = 5; // Sync with linux uhid_event_type::UHID_OUTPUT private static final byte UHID_EVENT_TYPE_UHID_OUTPUT = 6; Loading @@ -56,21 +57,45 @@ public class Device { private final Map<ByteBuffer, byte[]> mOutputs; private final OutputStream mOutputStream; private long mTimeToSend; private final Object mCond = new Object(); /** * The report id of the report received in UHID_EVENT_TYPE_SET_REPORT. * Used for SET_REPORT_REPLY. * This field gets overridden each time SET_REPORT is received. */ private int mResponseId; static { System.loadLibrary("hidcommand_jni"); } private static native long nativeOpenDevice(String name, int id, int vid, int pid, int bus, byte[] descriptor, DeviceCallback callback); private static native long nativeOpenDevice( String name, int id, int vid, int pid, int bus, 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 nativeSendSetReportReply(long ptr, int id, boolean success); private static native void nativeCloseDevice(long ptr); public Device(int id, String name, int vid, int pid, int bus, byte[] descriptor, byte[] report, SparseArray<byte[]> featureReports, Map<ByteBuffer, byte[]> outputs) { public Device( int id, String name, int vid, int pid, int bus, byte[] descriptor, byte[] report, SparseArray<byte[]> featureReports, Map<ByteBuffer, byte[]> outputs) { mId = id; mThread = new HandlerThread("HidDeviceHandler"); mThread.start(); Loading Loading @@ -100,6 +125,17 @@ public class Device { mHandler.sendMessageAtTime(msg, mTimeToSend); } public void setGetReportResponse(byte[] report) { mFeatureReports.put(report[0], report); } public void sendSetReportReply(boolean success) { Message msg = mHandler.obtainMessage(MSG_SEND_SET_REPORT_REPLY, mResponseId, success ? 1 : 0); mHandler.sendMessageAtTime(msg, mTimeToSend); } public void addDelay(int delay) { mTimeToSend = Math.max(SystemClock.uptimeMillis(), mTimeToSend) + delay; } Loading @@ -111,7 +147,8 @@ public class Device { synchronized (mCond) { mCond.wait(); } } catch (InterruptedException ignore) {} } catch (InterruptedException ignore) { } } private class DeviceHandler extends Handler { Loading @@ -127,8 +164,15 @@ public class Device { switch (msg.what) { case MSG_OPEN_DEVICE: SomeArgs args = (SomeArgs) msg.obj; mPtr = nativeOpenDevice((String) args.arg1, args.argi1, args.argi2, args.argi3, args.argi4, (byte[]) args.arg2, new DeviceCallback()); mPtr = nativeOpenDevice( (String) args.arg1, args.argi1, args.argi2, args.argi3, args.argi4, (byte[]) args.arg2, new DeviceCallback()); pauseEvents(); break; case MSG_SEND_REPORT: Loading @@ -145,6 +189,14 @@ public class Device { Log.e(TAG, "Tried to send feature report reply to closed device."); } break; case MSG_SEND_SET_REPORT_REPLY: if (mPtr != 0) { final boolean success = msg.arg2 == 1; nativeSendSetReportReply(mPtr, msg.arg1, success); } else { Log.e(TAG, "Tried to send set report reply to closed device."); } break; case MSG_CLOSE_DEVICE: if (mPtr != 0) { nativeCloseDevice(mPtr); Loading Loading @@ -173,13 +225,17 @@ public class Device { } private class DeviceCallback { public void onDeviceOpen() { mHandler.resumeEvents(); } public void onDeviceGetReport(int requestId, int reportId) { if (mFeatureReports == null) { Log.e(TAG, "Received GET_REPORT request for reportId=" + reportId Log.e( TAG, "Received GET_REPORT request for reportId=" + reportId + ", but 'feature_reports' section is not found"); return; } Loading Loading @@ -220,14 +276,15 @@ public class Device { } catch (IOException e) { throw new RuntimeException(e); } } // native callback public void onDeviceSetReport(byte rtype, byte[] data) { public void onDeviceSetReport(int id, byte rType, byte[] data) { // Used by sendSetReportReply() mResponseId = id; // We don't need to reply for the SET_REPORT but just send it to HID output for test // verification. sendReportOutput(UHID_EVENT_TYPE_SET_REPORT, rtype, data); sendReportOutput(UHID_EVENT_TYPE_SET_REPORT, rType, data); } // native callback Loading @@ -239,7 +296,8 @@ public class Device { } byte[] response = mOutputs.get(ByteBuffer.wrap(data)); if (response == null) { Log.i(TAG, Log.i( TAG, "Requested response for output " + Arrays.toString(data) + " is not found"); return; } Loading
cmds/hid/src/com/android/commands/hid/Event.java +30 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ public class Event { public static final String COMMAND_REGISTER = "register"; public static final String COMMAND_DELAY = "delay"; public static final String COMMAND_REPORT = "report"; public static final String COMMAND_SET_GET_REPORT_RESPONSE = "set_get_report_response"; public static final String COMMAND_SEND_SET_REPORT_REPLY = "send_set_report_reply"; // These constants come from "include/uapi/linux/input.h" in the kernel enum Bus { Loading Loading @@ -62,6 +64,7 @@ public class Event { private SparseArray<byte[]> mFeatureReports; private Map<ByteBuffer, byte[]> mOutputs; private int mDuration; private Boolean mReply; public int getId() { return mId; Loading Loading @@ -107,6 +110,10 @@ public class Event { return mDuration; } public Boolean getReply() { return mReply; } public String toString() { return "Event{id=" + mId + ", command=" + String.valueOf(mCommand) Loading @@ -119,6 +126,7 @@ public class Event { + ", feature_reports=" + mFeatureReports.toString() + ", outputs=" + mOutputs.toString() + ", duration=" + mDuration + ", success=" + mReply.toString() + "}"; } Loading Loading @@ -173,6 +181,10 @@ public class Event { mEvent.mDuration = duration; } public void setReply(boolean success) { mEvent.mReply = success; } public Event build() { if (mEvent.mId == -1) { throw new IllegalStateException("No event id"); Loading @@ -183,6 +195,16 @@ public class Event { if (mEvent.mDescriptor == null) { throw new IllegalStateException("Device registration is missing descriptor"); } } if (COMMAND_SET_GET_REPORT_RESPONSE.equals(mEvent.mCommand)) { if (mEvent.mReport == null) { throw new IllegalStateException("Report command is missing response data"); } } if (COMMAND_SEND_SET_REPORT_REPLY.equals(mEvent.mCommand)) { if (mEvent.mReply == null) { throw new IllegalStateException("Reply command is missing reply"); } } else if (COMMAND_DELAY.equals(mEvent.mCommand)) { if (mEvent.mDuration <= 0) { throw new IllegalStateException("Delay has missing or invalid duration"); Loading Loading @@ -246,6 +268,9 @@ public class Event { case "duration": eb.setDuration(readInt()); break; case "success": eb.setReply(readBool()); break; default: mReader.skipValue(); } Loading Loading @@ -292,6 +317,11 @@ public class Event { return Integer.decode(val); } private boolean readBool() throws IOException { String val = mReader.nextString(); return Boolean.parseBoolean(val); } private Bus readBus() throws IOException { String val = mReader.nextString(); return Bus.valueOf(val.toUpperCase()); Loading
cmds/hid/src/com/android/commands/hid/Hid.java +4 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,10 @@ public class Hid { d.addDelay(e.getDuration()); } else if (Event.COMMAND_REPORT.equals(e.getCommand())) { d.sendReport(e.getReport()); } else if (Event.COMMAND_SET_GET_REPORT_RESPONSE.equals(e.getCommand())) { d.setGetReportResponse(e.getReport()); } else if (Event.COMMAND_SEND_SET_REPORT_REPLY.equals(e.getCommand())) { d.sendSetReportReply(e.getReply()); } else { if (Event.COMMAND_REGISTER.equals(e.getCommand())) { error("Device id=" + e.getId() + " is already registered. Ignoring event."); Loading