diff options
Diffstat (limited to 'services/input/EventHub.cpp')
-rw-r--r-- | services/input/EventHub.cpp | 66 |
1 files changed, 56 insertions, 10 deletions
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp index 4d70d5f..e67c64c 100644 --- a/services/input/EventHub.cpp +++ b/services/input/EventHub.cpp @@ -49,6 +49,7 @@ #include <sys/ioctl.h> #include <sys/limits.h> #include <sys/sha1.h> +#include <sys/utsname.h> /* this macro is used to tell if "bit" is set in "array" * it selects a byte from the array, and does a boolean AND @@ -93,6 +94,14 @@ static String8 sha1(const String8& in) { return out; } +static void getLinuxRelease(int* major, int* minor) { + struct utsname info; + if (uname(&info) || sscanf(info.release, "%d.%d", major, minor) <= 0) { + *major = 0, *minor = 0; + ALOGE("Could not get linux version: %s", strerror(errno)); + } +} + static void setDescriptor(InputDeviceIdentifier& identifier) { // Compute a device descriptor that uniquely identifies the device. // The descriptor is assumed to be a stable identifier. Its value should not @@ -236,6 +245,11 @@ EventHub::EventHub(void) : result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem); LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d", errno); + + int major, minor; + getLinuxRelease(&major, &minor); + // EPOLLWAKEUP was introduced in kernel 3.5 + mUsingEpollWakeup = major > 3 || (major == 3 && minor >= 5); } EventHub::~EventHub(void) { @@ -509,8 +523,9 @@ bool EventHub::hasScanCode(int32_t deviceId, int32_t scanCode) const { bool EventHub::hasLed(int32_t deviceId, int32_t led) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device && led >= 0 && led <= LED_MAX) { - if (test_bit(led, device->ledBitmask)) { + int32_t sc; + if (device && mapLed(device, led, &sc) == NO_ERROR) { + if (test_bit(sc, device->ledBitmask)) { return true; } } @@ -520,12 +535,17 @@ bool EventHub::hasLed(int32_t deviceId, int32_t led) const { void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device && !device->isVirtual() && led >= 0 && led <= LED_MAX) { + setLedStateLocked(device, led, on); +} + +void EventHub::setLedStateLocked(Device* device, int32_t led, bool on) { + int32_t sc; + if (device && !device->isVirtual() && mapLed(device, led, &sc) != NAME_NOT_FOUND) { struct input_event ev; ev.time.tv_sec = 0; ev.time.tv_usec = 0; ev.type = EV_LED; - ev.code = led; + ev.code = sc; ev.value = on ? 1 : 0; ssize_t nWrite; @@ -1239,12 +1259,13 @@ status_t EventHub::openDeviceLocked(const char *devicePath) { if (device->classes & (INPUT_DEVICE_CLASS_JOYSTICK | INPUT_DEVICE_CLASS_GAMEPAD)) { device->controllerNumber = getNextControllerNumberLocked(device); + setLedForController(device); } // Register with epoll. struct epoll_event eventItem; memset(&eventItem, 0, sizeof(eventItem)); - eventItem.events = EPOLLIN; + eventItem.events = mUsingEpollWakeup ? EPOLLIN : EPOLLIN | EPOLLWAKEUP; eventItem.data.u32 = deviceId; if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) { ALOGE("Could not add device fd to epoll instance. errno=%d", errno); @@ -1252,9 +1273,14 @@ status_t EventHub::openDeviceLocked(const char *devicePath) { return -1; } - // Enable wake-lock behavior on kernels that support it. - // TODO: Only need this for devices that can really wake the system. - bool usingSuspendBlockIoctl = !ioctl(fd, EVIOCSSUSPENDBLOCK, 1); + String8 wakeMechanism("EPOLLWAKEUP"); + if (!mUsingEpollWakeup) { + if (ioctl(fd, EVIOCSSUSPENDBLOCK, 1)) { + wakeMechanism = "<none>"; + } else { + wakeMechanism = "EVIOCSSUSPENDBLOCK"; + } + } // Tell the kernel that we want to use the monotonic clock for reporting timestamps // associated with input events. This is important because the input system @@ -1276,14 +1302,14 @@ status_t EventHub::openDeviceLocked(const char *devicePath) { ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, " "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, " - "usingSuspendBlockIoctl=%s, usingClockIoctl=%s", + "wakeMechanism=%s, usingClockIoctl=%s", deviceId, fd, devicePath, device->identifier.name.string(), device->classes, device->configurationFile.string(), device->keyMap.keyLayoutFile.string(), device->keyMap.keyCharacterMapFile.string(), toString(mBuiltInKeyboardId == deviceId), - toString(usingSuspendBlockIoctl), toString(usingClockIoctl)); + wakeMechanism.string(), toString(usingClockIoctl)); addDeviceLocked(device); return 0; @@ -1372,6 +1398,11 @@ void EventHub::releaseControllerNumberLocked(Device* device) { mControllerNumbers.clearBit(static_cast<uint32_t>(num - 1)); } +void EventHub::setLedForController(Device* device) { + for (int i = 0; i < MAX_CONTROLLER_LEDS; i++) { + setLedStateLocked(device, ALED_CONTROLLER_1 + i, device->controllerNumber == i + 1); + } +} bool EventHub::hasKeycodeLocked(Device* device, int keycode) const { if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) { @@ -1391,6 +1422,21 @@ bool EventHub::hasKeycodeLocked(Device* device, int keycode) const { return false; } +status_t EventHub::mapLed(Device* device, int32_t led, int32_t* outScanCode) const { + if (!device->keyMap.haveKeyLayout() || !device->ledBitmask) { + return NAME_NOT_FOUND; + } + + int32_t scanCode; + if(device->keyMap.keyLayoutMap->findScanCodeForLed(led, &scanCode) != NAME_NOT_FOUND) { + if(scanCode >= 0 && scanCode <= LED_MAX && test_bit(scanCode, device->ledBitmask)) { + *outScanCode = scanCode; + return NO_ERROR; + } + } + return NAME_NOT_FOUND; +} + status_t EventHub::closeDeviceByPathLocked(const char *devicePath) { Device* device = getDeviceByPathLocked(devicePath); if (device) { |