Configure device classes for evdev devices.
Change-Id: Ia75b71253771d9d558c59411e27f8a51e352fb8b
diff --git a/modules/input/evdev/EvdevModule.cpp b/modules/input/evdev/EvdevModule.cpp
index f6df219..1171a1a 100644
--- a/modules/input/evdev/EvdevModule.cpp
+++ b/modules/input/evdev/EvdevModule.cpp
@@ -55,7 +55,7 @@
EvdevModule::EvdevModule(InputHost inputHost) :
mInputHost(inputHost),
- mDeviceManager(std::make_shared<InputDeviceManager>()),
+ mDeviceManager(std::make_shared<InputDeviceManager>(mInputHost)),
mInputHub(std::make_unique<InputHub>(mDeviceManager)) {}
void EvdevModule::init() {
diff --git a/modules/input/evdev/InputDevice.cpp b/modules/input/evdev/InputDevice.cpp
index 16f8039..883d6d4 100644
--- a/modules/input/evdev/InputDevice.cpp
+++ b/modules/input/evdev/InputDevice.cpp
@@ -17,10 +17,14 @@
#define LOG_TAG "InputDevice"
#define LOG_NDEBUG 0
+// Enables debug output for processing input events
+#define DEBUG_INPUT_EVENTS 0
+
#include <linux/input.h>
#define __STDC_FORMAT_MACROS
#include <cinttypes>
+#include <cstdlib>
#include <string>
#include <utils/Log.h>
@@ -34,18 +38,177 @@
namespace android {
-EvdevDevice::EvdevDevice(const std::shared_ptr<InputDeviceNode>& node) :
- mDeviceNode(node) {}
+static InputBus getInputBus(const std::shared_ptr<InputDeviceNode>& node) {
+ switch (node->getBusType()) {
+ case BUS_USB:
+ return INPUT_BUS_USB;
+ case BUS_BLUETOOTH:
+ return INPUT_BUS_BT;
+ case BUS_RS232:
+ return INPUT_BUS_SERIAL;
+ default:
+ // TODO: check for other linux bus types that might not be built-in
+ return INPUT_BUS_BUILTIN;
+ }
+}
+
+static uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses) {
+ // Touch devices get dibs on touch-related axes.
+ if (deviceClasses & INPUT_DEVICE_CLASS_TOUCH) {
+ switch (axis) {
+ case ABS_X:
+ case ABS_Y:
+ case ABS_PRESSURE:
+ case ABS_TOOL_WIDTH:
+ case ABS_DISTANCE:
+ case ABS_TILT_X:
+ case ABS_TILT_Y:
+ case ABS_MT_SLOT:
+ case ABS_MT_TOUCH_MAJOR:
+ case ABS_MT_TOUCH_MINOR:
+ case ABS_MT_WIDTH_MAJOR:
+ case ABS_MT_WIDTH_MINOR:
+ case ABS_MT_ORIENTATION:
+ case ABS_MT_POSITION_X:
+ case ABS_MT_POSITION_Y:
+ case ABS_MT_TOOL_TYPE:
+ case ABS_MT_BLOB_ID:
+ case ABS_MT_TRACKING_ID:
+ case ABS_MT_PRESSURE:
+ case ABS_MT_DISTANCE:
+ return INPUT_DEVICE_CLASS_TOUCH;
+ }
+ }
+
+ // External stylus gets the pressure axis
+ if (deviceClasses & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
+ if (axis == ABS_PRESSURE) {
+ return INPUT_DEVICE_CLASS_EXTERNAL_STYLUS;
+ }
+ }
+
+ // Joystick devices get the rest.
+ return INPUT_DEVICE_CLASS_JOYSTICK;
+}
+
+static bool getBooleanProperty(const InputProperty& prop) {
+ const char* propValue = prop.getValue();
+ if (propValue == nullptr) return false;
+
+ char* end;
+ int value = std::strtol(propValue, &end, 10);
+ if (*end != '\0') {
+ ALOGW("Expected boolean for property %s; value=%s", prop.getKey(), propValue);
+ return false;
+ }
+ return value;
+}
+
+static void setDeviceClasses(const InputDeviceNode* node, uint32_t* classes) {
+ // See if this is a keyboard. Ignore everything in the button range except
+ // for joystick and gamepad buttons which are handled like keyboards for the
+ // most part.
+ bool haveKeyboardKeys = node->hasKeyInRange(0, BTN_MISC) ||
+ node->hasKeyInRange(KEY_OK, KEY_CNT);
+ bool haveGamepadButtons = node->hasKeyInRange(BTN_MISC, BTN_MOUSE) ||
+ node->hasKeyInRange(BTN_JOYSTICK, BTN_DIGI);
+ if (haveKeyboardKeys || haveGamepadButtons) {
+ *classes |= INPUT_DEVICE_CLASS_KEYBOARD;
+ }
+
+ // See if this is a cursor device such as a trackball or mouse.
+ if (node->hasKey(BTN_MOUSE)
+ && node->hasRelativeAxis(REL_X)
+ && node->hasRelativeAxis(REL_Y)) {
+ *classes |= INPUT_DEVICE_CLASS_CURSOR;
+ }
+
+ // See if this is a touch pad.
+ // Is this a new modern multi-touch driver?
+ if (node->hasAbsoluteAxis(ABS_MT_POSITION_X)
+ && node->hasAbsoluteAxis(ABS_MT_POSITION_Y)) {
+ // Some joysticks such as the PS3 controller report axes that conflict
+ // with the ABS_MT range. Try to confirm that the device really is a
+ // touch screen.
+ if (node->hasKey(BTN_TOUCH) || !haveGamepadButtons) {
+ *classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
+ }
+ // Is this an old style single-touch driver?
+ } else if (node->hasKey(BTN_TOUCH)
+ && node->hasAbsoluteAxis(ABS_X)
+ && node->hasAbsoluteAxis(ABS_Y)) {
+ *classes != INPUT_DEVICE_CLASS_TOUCH;
+ // Is this a BT stylus?
+ } else if ((node->hasAbsoluteAxis(ABS_PRESSURE) || node->hasKey(BTN_TOUCH))
+ && !node->hasAbsoluteAxis(ABS_X) && !node->hasAbsoluteAxis(ABS_Y)) {
+ *classes |= INPUT_DEVICE_CLASS_EXTERNAL_STYLUS;
+ // Keyboard will try to claim some of the buttons but we really want to
+ // reserve those so we can fuse it with the touch screen data, so just
+ // take them back. Note this means an external stylus cannot also be a
+ // keyboard device.
+ *classes &= ~INPUT_DEVICE_CLASS_KEYBOARD;
+ }
+
+ // See if this device is a joystick.
+ // Assumes that joysticks always have gamepad buttons in order to
+ // distinguish them from other devices such as accelerometers that also have
+ // absolute axes.
+ if (haveGamepadButtons) {
+ uint32_t assumedClasses = *classes | INPUT_DEVICE_CLASS_JOYSTICK;
+ for (int i = 0; i < ABS_CNT; ++i) {
+ if (node->hasAbsoluteAxis(i)
+ && getAbsAxisUsage(i, assumedClasses) == INPUT_DEVICE_CLASS_JOYSTICK) {
+ *classes = assumedClasses;
+ break;
+ }
+ }
+ }
+
+ // Check whether this device has switches.
+ for (int i = 0; i < SW_CNT; ++i) {
+ if (node->hasSwitch(i)) {
+ *classes |= INPUT_DEVICE_CLASS_SWITCH;
+ break;
+ }
+ }
+
+ // Check whether this device supports the vibrator.
+ if (node->hasForceFeedback(FF_RUMBLE)) {
+ *classes |= INPUT_DEVICE_CLASS_VIBRATOR;
+ }
+
+ // If the device isn't recognized as something we handle, don't monitor it.
+ // TODO
+
+ ALOGD("device %s classes=0x%x", node->getPath().c_str(), *classes);
+}
+
+EvdevDevice::EvdevDevice(InputHost host, const std::shared_ptr<InputDeviceNode>& node) :
+ mHost(host), mDeviceNode(node) {
+
+ InputBus bus = getInputBus(node);
+ mInputId = mHost.createDeviceIdentifier(
+ node->getName().c_str(),
+ node->getProductId(),
+ node->getVendorId(),
+ bus,
+ node->getUniqueId().c_str());
+
+ InputPropertyMap propMap = mHost.getDevicePropertyMap(mInputId);
+ setDeviceClasses(mDeviceNode.get(), &mClasses);
+}
void EvdevDevice::processInput(InputEvent& event, nsecs_t currentTime) {
+#if DEBUG_INPUT_EVENTS
std::string log;
log.append("---InputEvent for device %s---\n");
log.append(" when: %" PRId64 "\n");
log.append(" type: %d\n");
log.append(" code: %d\n");
log.append(" value: %d\n");
- ALOGV(log.c_str(), mDeviceNode->getPath().c_str(), event.when, event.type, event.code,
+ ALOGD(log.c_str(), mDeviceNode->getPath().c_str(), event.when, event.type, event.code,
event.value);
+#endif
if (event.type == EV_MSC) {
if (event.code == MSC_ANDROID_TIME_SEC) {
diff --git a/modules/input/evdev/InputDevice.h b/modules/input/evdev/InputDevice.h
index 7a99f90..b4f3244 100644
--- a/modules/input/evdev/InputDevice.h
+++ b/modules/input/evdev/InputDevice.h
@@ -21,6 +21,7 @@
#include <utils/Timers.h>
+#include "InputHost.h"
#include "InputHub.h"
namespace android {
@@ -33,6 +34,7 @@
public:
virtual void processInput(InputEvent& event, nsecs_t currentTime) = 0;
+ virtual uint32_t getInputClasses() = 0;
protected:
InputDeviceInterface() = default;
virtual ~InputDeviceInterface() = default;
@@ -43,18 +45,69 @@
*/
class EvdevDevice : public InputDeviceInterface {
public:
- explicit EvdevDevice(const std::shared_ptr<InputDeviceNode>& node);
+ EvdevDevice(InputHost host, const std::shared_ptr<InputDeviceNode>& node);
virtual ~EvdevDevice() override = default;
virtual void processInput(InputEvent& event, nsecs_t currentTime) override;
+ virtual uint32_t getInputClasses() override { return mClasses; }
private:
+ InputHost mHost;
std::shared_ptr<InputDeviceNode> mDeviceNode;
+ InputDeviceIdentifier mInputId;
+ uint32_t mClasses = 0;
int32_t mOverrideSec = 0;
int32_t mOverrideUsec = 0;
};
+/* Input device classes. */
+enum {
+ /* The input device is a keyboard or has buttons. */
+ INPUT_DEVICE_CLASS_KEYBOARD = 0x00000001,
+
+ /* The input device is an alpha-numeric keyboard (not just a dial pad). */
+ INPUT_DEVICE_CLASS_ALPHAKEY = 0x00000002,
+
+ /* The input device is a touchscreen or a touchpad (either single-touch or multi-touch). */
+ INPUT_DEVICE_CLASS_TOUCH = 0x00000004,
+
+ /* The input device is a cursor device such as a trackball or mouse. */
+ INPUT_DEVICE_CLASS_CURSOR = 0x00000008,
+
+ /* The input device is a multi-touch touchscreen. */
+ INPUT_DEVICE_CLASS_TOUCH_MT = 0x00000010,
+
+ /* The input device is a directional pad (implies keyboard, has DPAD keys). */
+ INPUT_DEVICE_CLASS_DPAD = 0x00000020,
+
+ /* The input device is a gamepad (implies keyboard, has BUTTON keys). */
+ INPUT_DEVICE_CLASS_GAMEPAD = 0x00000040,
+
+ /* The input device has switches. */
+ INPUT_DEVICE_CLASS_SWITCH = 0x00000080,
+
+ /* The input device is a joystick (implies gamepad, has joystick absolute axes). */
+ INPUT_DEVICE_CLASS_JOYSTICK = 0x00000100,
+
+ /* The input device has a vibrator (supports FF_RUMBLE). */
+ INPUT_DEVICE_CLASS_VIBRATOR = 0x00000200,
+
+ /* The input device has a microphone. */
+ // TODO: remove this and let the host take care of it
+ INPUT_DEVICE_CLASS_MIC = 0x00000400,
+
+ /* The input device is an external stylus (has data we want to fuse with touch data). */
+ INPUT_DEVICE_CLASS_EXTERNAL_STYLUS = 0x00000800,
+
+ /* The input device is virtual (not a real device, not part of UI configuration). */
+ /* not used - INPUT_DEVICE_CLASS_VIRTUAL = 0x40000000, */
+
+ /* The input device is external (not built-in). */
+ // TODO: remove this and let the host take care of it?
+ INPUT_DEVICE_CLASS_EXTERNAL = 0x80000000,
+};
+
} // namespace android
#endif // ANDROID_INPUT_DEVICE_H_
diff --git a/modules/input/evdev/InputDeviceManager.cpp b/modules/input/evdev/InputDeviceManager.cpp
index 79a9610..f21d6d1 100644
--- a/modules/input/evdev/InputDeviceManager.cpp
+++ b/modules/input/evdev/InputDeviceManager.cpp
@@ -34,7 +34,7 @@
}
void InputDeviceManager::onDeviceAdded(const std::shared_ptr<InputDeviceNode>& node) {
- mDevices[node] = std::make_shared<EvdevDevice>(node);
+ mDevices[node] = std::make_shared<EvdevDevice>(mHost, node);
}
void InputDeviceManager::onDeviceRemoved(const std::shared_ptr<InputDeviceNode>& node) {
diff --git a/modules/input/evdev/InputDeviceManager.h b/modules/input/evdev/InputDeviceManager.h
index 2c0ffc8..25dd912 100644
--- a/modules/input/evdev/InputDeviceManager.h
+++ b/modules/input/evdev/InputDeviceManager.h
@@ -23,6 +23,7 @@
#include <utils/Timers.h>
#include "InputDevice.h"
+#include "InputHost.h"
#include "InputHub.h"
namespace android {
@@ -34,6 +35,8 @@
*/
class InputDeviceManager : public InputCallbackInterface {
public:
+ explicit InputDeviceManager(InputHost host) :
+ mHost(host) {}
virtual ~InputDeviceManager() override = default;
virtual void onInputEvent(const std::shared_ptr<InputDeviceNode>& node, InputEvent& event,
@@ -42,6 +45,8 @@
virtual void onDeviceRemoved(const std::shared_ptr<InputDeviceNode>& node) override;
private:
+ InputHost mHost;
+
template<class T, class U>
using DeviceMap = std::unordered_map<std::shared_ptr<T>, std::shared_ptr<U>>;
diff --git a/modules/input/evdev/InputHost.cpp b/modules/input/evdev/InputHost.cpp
index 6a65fcd..74a5f8a 100644
--- a/modules/input/evdev/InputHost.cpp
+++ b/modules/input/evdev/InputHost.cpp
@@ -51,11 +51,16 @@
mCallbacks.input_free_device_property(mHost, mProperty);
}
-const char* InputProperty::getKey() {
+InputProperty::InputProperty(InputProperty&& rhs) :
+ InputHostBase(rhs), mProperty(std::move(rhs.mProperty)) {
+ rhs.mProperty = nullptr;
+}
+
+const char* InputProperty::getKey() const {
return mCallbacks.input_get_property_key(mHost, mProperty);
}
-const char* InputProperty::getValue() {
+const char* InputProperty::getValue() const {
return mCallbacks.input_get_property_value(mHost, mProperty);
}
@@ -63,7 +68,12 @@
mCallbacks.input_free_device_property_map(mHost, mMap);
}
-InputProperty InputPropertyMap::getDeviceProperty(const char* key) {
+InputPropertyMap::InputPropertyMap(InputPropertyMap&& rhs) :
+ InputHostBase(rhs), mMap(std::move(rhs.mMap)) {
+ rhs.mMap = nullptr;
+}
+
+InputProperty InputPropertyMap::getDeviceProperty(const char* key) const {
return InputProperty(mHost, mCallbacks,
mCallbacks.input_get_device_property(mHost, mMap, key));
}
diff --git a/modules/input/evdev/InputHost.h b/modules/input/evdev/InputHost.h
index 98ce26f..d6a04d9 100644
--- a/modules/input/evdev/InputHost.h
+++ b/modules/input/evdev/InputHost.h
@@ -43,6 +43,9 @@
InputHostBase(input_host_t* host, input_host_callbacks_t cb) : mHost(host), mCallbacks(cb) {}
virtual ~InputHostBase() = default;
+ InputHostBase(const InputHostBase& rhs) = default;
+ InputHostBase(InputHostBase&& rhs) = default;
+
input_host_t* mHost;
input_host_callbacks_t mCallbacks;
};
@@ -117,12 +120,11 @@
operator input_property_t*() { return mProperty; }
- const char* getKey();
- const char* getValue();
+ const char* getKey() const;
+ const char* getValue() const;
- // Default move constructor transfers ownership of the input_property_t
- // pointer.
- InputProperty(InputProperty&& rhs) = default;
+ // Transfers ownership of the input_property_t pointer.
+ InputProperty(InputProperty&& rhs);
// Prevent copy/assign because of the ownership of the underlying
// input_property_t pointer.
@@ -145,11 +147,10 @@
operator input_property_map_t*() { return mMap; }
- InputProperty getDeviceProperty(const char* key);
+ InputProperty getDeviceProperty(const char* key) const;
- // Default move constructor transfers ownership of the input_property_map_t
- // pointer.
- InputPropertyMap(InputPropertyMap&& rhs) = default;
+ // Transfers ownership of the input_property_map_t pointer.
+ InputPropertyMap(InputPropertyMap&& rhs);
// Prevent copy/assign because of the ownership of the underlying
// input_property_map_t pointer.
diff --git a/modules/input/evdev/InputHub-internal.h b/modules/input/evdev/InputHub-internal.h
new file mode 100644
index 0000000..b4f1297
--- /dev/null
+++ b/modules/input/evdev/InputHub-internal.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INPUT_HUB_INTERNAL_H_
+#define ANDROID_INPUT_HUB_INTERNAL_H_
+
+namespace android {
+namespace internal {
+
+/** Test whether any bits in the interval [start, end) are set in the array. */
+bool testBitInRange(const uint8_t arr[], size_t start, size_t end);
+
+} // namespace internal
+} // namespace android
+
+#endif // ANDROID_INPUT_HUB_INTERNAL_H_
diff --git a/modules/input/evdev/InputHub.cpp b/modules/input/evdev/InputHub.cpp
index ee64b29..8c48345 100644
--- a/modules/input/evdev/InputHub.cpp
+++ b/modules/input/evdev/InputHub.cpp
@@ -15,7 +15,10 @@
*/
#define LOG_TAG "InputHub"
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
+
+// Enables debug output for hasKeyInRange
+#define DEBUG_KEY_RANGE 0
#include <dirent.h>
#include <errno.h>
@@ -34,6 +37,7 @@
#include <vector>
#include "InputHub.h"
+#include "InputHub-internal.h"
#include <android/input.h>
#include <hardware_legacy/power.h>
@@ -56,6 +60,57 @@
return (bits + 7) / 8;
}
+namespace internal {
+
+#if DEBUG_KEY_RANGE
+static const char* bitstrings[16] = {
+ "0000", "0001", "0010", "0011",
+ "0100", "0101", "0110", "0111",
+ "1000", "1001", "1010", "1011",
+ "1100", "1101", "1110", "1111",
+};
+#endif
+
+bool testBitInRange(const uint8_t arr[], size_t start, size_t end) {
+#if DEBUG_KEY_RANGE
+ ALOGD("testBitInRange(%d, %d)", start, end);
+#endif
+ // Invalid range! This is nonsense; just say no.
+ if (end <= start) return false;
+
+ // Find byte array indices. The end is not included in the range, nor is
+ // endIndex. Round up for endIndex.
+ size_t startIndex = start / 8;
+ size_t endIndex = (end + 7) / 8;
+#if DEBUG_KEY_RANGE
+ ALOGD("startIndex=%d, endIndex=%d", startIndex, endIndex);
+#endif
+ for (size_t i = startIndex; i < endIndex; ++i) {
+ uint8_t bits = arr[i];
+ uint8_t mask = 0xff;
+#if DEBUG_KEY_RANGE
+ ALOGD("block %04d: %s%s", i, bitstrings[bits >> 4], bitstrings[bits & 0x0f]);
+#endif
+ if (bits) {
+ // Mask off bits before our start bit
+ if (i == startIndex) {
+ mask &= 0xff << (start % 8);
+ }
+ // Mask off bits after our end bit
+ if (i == endIndex - 1 && (end % 8)) {
+ mask &= 0xff >> (8 - (end % 8));
+ }
+#if DEBUG_KEY_RANGE
+ ALOGD("mask: %s%s", bitstrings[mask >> 4], bitstrings[mask & 0x0f]);
+#endif
+ // Test the index against the mask
+ if (bits & mask) return true;
+ }
+ }
+ return false;
+}
+} // namespace internal
+
static void getLinuxRelease(int* major, int* minor) {
struct utsname info;
if (uname(&info) || sscanf(info.release, "%d.%d", major, minor) <= 0) {
@@ -74,7 +129,6 @@
caphdr->version = _LINUX_CAPABILITY_VERSION_3;
LOG_ALWAYS_FATAL_IF(capget(caphdr, capdata) != 0,
"Could not get process capabilities. errno=%d", errno);
- ALOGV("effective capabilities: %08x %08x", capdata[0].effective, capdata[1].effective);
int idx = CAP_TO_INDEX(capability);
return capdata[idx].effective & CAP_TO_MASK(capability);
}
@@ -102,16 +156,20 @@
virtual uint16_t getVersion() const override { return mVersion; }
virtual bool hasKey(int32_t key) const override;
- virtual bool hasRelativeAxis(int axis) const override;
- virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const override;
+ virtual bool hasKeyInRange(int32_t start, int32_t end) const override;
+ virtual bool hasRelativeAxis(int32_t axis) const override;
+ virtual bool hasAbsoluteAxis(int32_t axis) const override;
+ virtual bool hasSwitch(int32_t sw) const override;
+ virtual bool hasForceFeedback(int32_t ff) const override;
virtual bool hasInputProperty(int property) const override;
virtual int32_t getKeyState(int32_t key) const override;
virtual int32_t getSwitchState(int32_t sw) const override;
+ virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const override;
virtual status_t getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const override;
virtual void vibrate(nsecs_t duration) override;
- virtual void cancelVibrate(int32_t deviceId) override;
+ virtual void cancelVibrate() override;
virtual void disableDriverKeyRepeat() override;
@@ -272,6 +330,10 @@
return false;
}
+bool EvdevDeviceNode::hasKeyInRange(int32_t startKey, int32_t endKey) const {
+ return internal::testBitInRange(mKeyBitmask, startKey, endKey);
+}
+
bool EvdevDeviceNode::hasRelativeAxis(int axis) const {
if (axis >= 0 && axis <= REL_MAX) {
return testBit(axis, mRelBitmask);
@@ -279,6 +341,13 @@
return false;
}
+bool EvdevDeviceNode::hasAbsoluteAxis(int axis) const {
+ if (axis >= 0 && axis <= ABS_MAX) {
+ return getAbsoluteAxisInfo(axis) != nullptr;
+ }
+ return false;
+}
+
const AbsoluteAxisInfo* EvdevDeviceNode::getAbsoluteAxisInfo(int32_t axis) const {
if (axis < 0 || axis > ABS_MAX) {
return nullptr;
@@ -291,6 +360,20 @@
return nullptr;
}
+bool EvdevDeviceNode::hasSwitch(int32_t sw) const {
+ if (sw >= 0 && sw <= SW_MAX) {
+ return testBit(sw, mSwBitmask);
+ }
+ return false;
+}
+
+bool EvdevDeviceNode::hasForceFeedback(int32_t ff) const {
+ if (ff >= 0 && ff <= FF_MAX) {
+ return testBit(ff, mFfBitmask);
+ }
+ return false;
+}
+
bool EvdevDeviceNode::hasInputProperty(int property) const {
if (property >= 0 && property <= INPUT_PROP_MAX) {
return testBit(property, mPropBitmask);
@@ -371,7 +454,7 @@
mFfEffectPlaying = true;
}
-void EvdevDeviceNode::cancelVibrate(int32_t deviceId) {
+void EvdevDeviceNode::cancelVibrate() {
if (mFfEffectPlaying) {
mFfEffectPlaying = false;
diff --git a/modules/input/evdev/InputHub.h b/modules/input/evdev/InputHub.h
index dfab3db..1abdc09 100644
--- a/modules/input/evdev/InputHub.h
+++ b/modules/input/evdev/InputHub.h
@@ -56,29 +56,55 @@
*/
class InputDeviceNode {
public:
+ /** Get the Linux device path for the node. */
virtual const std::string& getPath() const = 0;
+ /** Get the name of the device returned by the driver. */
virtual const std::string& getName() const = 0;
+ /** Get the location of the device returned by the driver. */
virtual const std::string& getLocation() const = 0;
+ /** Get the unique id of the device returned by the driver. */
virtual const std::string& getUniqueId() const = 0;
+ /** Get the bus type of the device returned by the driver. */
virtual uint16_t getBusType() const = 0;
+ /** Get the vendor id of the device returned by the driver. */
virtual uint16_t getVendorId() const = 0;
+ /** Get the product id of the device returned by the driver. */
virtual uint16_t getProductId() const = 0;
+ /** Get the version of the device driver. */
virtual uint16_t getVersion() const = 0;
+ /** Returns true if the device has the key. */
virtual bool hasKey(int32_t key) const = 0;
- virtual bool hasRelativeAxis(int axis) const = 0;
- virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const = 0;
+ /** Returns true if the device has a key in the range [startKey, endKey). */
+ virtual bool hasKeyInRange(int32_t startKey, int32_t endKey) const = 0;
+ /** Returns true if the device has the relative axis. */
+ virtual bool hasRelativeAxis(int32_t axis) const = 0;
+ /** Returns true if the device has the absolute axis. */
+ virtual bool hasAbsoluteAxis(int32_t axis) const = 0;
+ /** Returns true if the device has the switch. */
+ virtual bool hasSwitch(int32_t sw) const = 0;
+ /** Returns true if the device has the force feedback method. */
+ virtual bool hasForceFeedback(int32_t ff) const = 0;
+ /** Returns true if the device has the input property. */
virtual bool hasInputProperty(int property) const = 0;
+ /** Returns the state of the key. */
virtual int32_t getKeyState(int32_t key) const = 0;
+ /** Returns the state of the switch. */
virtual int32_t getSwitchState(int32_t sw) const = 0;
+ /** Returns information about the absolute axis. */
+ virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const = 0;
+ /** Returns the value of the absolute axis. */
virtual status_t getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const = 0;
+ /** Vibrate the device for duration ns. */
virtual void vibrate(nsecs_t duration) = 0;
- virtual void cancelVibrate(int32_t deviceId) = 0;
+ /** Stop vibration on the device. */
+ virtual void cancelVibrate() = 0;
+ /** Disable key repeat for the device in the driver. */
virtual void disableDriverKeyRepeat() = 0;
protected: