blob: f4682174acf166ec1048074e4645997f8d6d1868 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001//
2// Copyright 2005 The Android Open Source Project
3//
4// Handle events, like key input and vsync.
5//
6// The goal is to provide an optimized solution for Linux, not an
7// implementation that works well across all platforms. We expect
8// events to arrive on file descriptors, so that we can use a select()
9// select() call to sleep.
10//
11// We can't select() on anything but network sockets in Windows, so we
12// provide an alternative implementation of waitEvent for that platform.
13//
14#define LOG_TAG "EventHub"
15
16//#define LOG_NDEBUG 0
17
18#include <ui/EventHub.h>
19#include <hardware_legacy/power.h>
20
21#include <cutils/properties.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080022#include <utils/Log.h>
23#include <utils/Timers.h>
Mathias Agopiane0c32202009-05-31 19:13:00 -070024#include <utils/threads.h>
Mathias Agopiane0c32202009-05-31 19:13:00 -070025#include <utils/Errors.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080026
27#include <stdlib.h>
28#include <stdio.h>
29#include <unistd.h>
30#include <fcntl.h>
31#include <memory.h>
32#include <errno.h>
33#include <assert.h>
34
Jeff Browna3477c82010-11-10 16:03:06 -080035#include <ui/KeyLayoutMap.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080036
37#include <string.h>
38#include <stdint.h>
39#include <dirent.h>
40#ifdef HAVE_INOTIFY
41# include <sys/inotify.h>
42#endif
43#ifdef HAVE_ANDROID_OS
44# include <sys/limits.h> /* not part of Linux */
45#endif
46#include <sys/poll.h>
47#include <sys/ioctl.h>
48
49/* this macro is used to tell if "bit" is set in "array"
50 * it selects a byte from the array, and does a boolean AND
51 * operation with a byte that only has the relevant bit set.
52 * eg. to check for the 12th bit, we do (array[1] & 1<<4)
53 */
54#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8)))
55
Jeff Brown8575a872010-06-30 16:10:35 -070056/* this macro computes the number of bytes needed to represent a bit array of the specified size */
57#define sizeof_bit_array(bits) ((bits + 7) / 8)
58
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080059#define ID_MASK 0x0000ffff
60#define SEQ_MASK 0x7fff0000
61#define SEQ_SHIFT 16
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080062
Dianne Hackbornc5917362009-08-04 05:49:43 -070063#ifndef ABS_MT_TOUCH_MAJOR
64#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
65#endif
66
67#ifndef ABS_MT_POSITION_X
68#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
69#endif
70
71#ifndef ABS_MT_POSITION_Y
72#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
73#endif
74
Jeff Brown2806e382010-10-01 17:46:21 -070075#define INDENT " "
76#define INDENT2 " "
77#define INDENT3 " "
78
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080079namespace android {
80
81static const char *WAKE_LOCK_ID = "KeyEvents";
82static const char *device_path = "/dev/input";
83
84/* return the larger integer */
85static inline int max(int v1, int v2)
86{
87 return (v1 > v2) ? v1 : v2;
88}
89
Jeff Brown2806e382010-10-01 17:46:21 -070090static inline const char* toString(bool value) {
91 return value ? "true" : "false";
92}
93
Iliyan Malchev34193b32009-08-06 14:50:08 -070094EventHub::device_t::device_t(int32_t _id, const char* _path, const char* name)
95 : id(_id), path(_path), name(name), classes(0)
Jeff Browna3477c82010-11-10 16:03:06 -080096 , keyBitmask(NULL), layoutMap(NULL), fd(-1), next(NULL) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080097}
98
99EventHub::device_t::~device_t() {
100 delete [] keyBitmask;
101 delete layoutMap;
102}
103
104EventHub::EventHub(void)
Jeff Brown6a817e22010-09-12 17:55:08 -0700105 : mError(NO_INIT), mHaveFirstKeyboard(false), mFirstKeyboardId(-1)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800106 , mDevicesById(0), mNumDevicesById(0)
107 , mOpeningDevices(0), mClosingDevices(0)
Jeff Brown1ad00e92010-10-01 18:55:43 -0700108 , mDevices(0), mFDs(0), mFDCount(0), mOpened(false), mNeedToSendFinishedDeviceScan(false)
Jeff Brown82763072010-08-17 16:48:25 -0700109 , mInputBufferIndex(0), mInputBufferCount(0), mInputDeviceIndex(0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800110{
111 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
112#ifdef EV_SW
113 memset(mSwitches, 0, sizeof(mSwitches));
114#endif
115}
116
117/*
118 * Clean up.
119 */
120EventHub::~EventHub(void)
121{
122 release_wake_lock(WAKE_LOCK_ID);
123 // we should free stuff here...
124}
125
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800126status_t EventHub::errorCheck() const
127{
128 return mError;
129}
130
131String8 EventHub::getDeviceName(int32_t deviceId) const
132{
133 AutoMutex _l(mLock);
Jeff Brown2806e382010-10-01 17:46:21 -0700134 device_t* device = getDeviceLocked(deviceId);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800135 if (device == NULL) return String8();
136 return device->name;
137}
138
139uint32_t EventHub::getDeviceClasses(int32_t deviceId) const
140{
141 AutoMutex _l(mLock);
Jeff Brown2806e382010-10-01 17:46:21 -0700142 device_t* device = getDeviceLocked(deviceId);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800143 if (device == NULL) return 0;
144 return device->classes;
145}
146
Jeff Browne57e8952010-07-23 21:28:06 -0700147status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
148 RawAbsoluteAxisInfo* outAxisInfo) const {
Jeff Brown38a7fab2010-08-30 03:02:23 -0700149 outAxisInfo->clear();
Jeff Browne57e8952010-07-23 21:28:06 -0700150
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800151 AutoMutex _l(mLock);
Jeff Brown2806e382010-10-01 17:46:21 -0700152 device_t* device = getDeviceLocked(deviceId);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800153 if (device == NULL) return -1;
154
155 struct input_absinfo info;
156
Jens Gulin7dcaa582010-06-22 22:21:57 +0200157 if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
Jeff Browne57e8952010-07-23 21:28:06 -0700158 LOGW("Error reading absolute controller %d for device %s fd %d\n",
Jens Gulin7dcaa582010-06-22 22:21:57 +0200159 axis, device->name.string(), device->fd);
Jeff Browne57e8952010-07-23 21:28:06 -0700160 return -errno;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800161 }
Jeff Browne57e8952010-07-23 21:28:06 -0700162
163 if (info.minimum != info.maximum) {
164 outAxisInfo->valid = true;
165 outAxisInfo->minValue = info.minimum;
166 outAxisInfo->maxValue = info.maximum;
167 outAxisInfo->flat = info.flat;
168 outAxisInfo->fuzz = info.fuzz;
169 }
170 return OK;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800171}
172
Jeff Browne57e8952010-07-23 21:28:06 -0700173int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
Jeff Browne839a582010-04-22 18:58:52 -0700174 if (scanCode >= 0 && scanCode <= KEY_MAX) {
175 AutoMutex _l(mLock);
176
Jeff Brown2806e382010-10-01 17:46:21 -0700177 device_t* device = getDeviceLocked(deviceId);
Jeff Browne57e8952010-07-23 21:28:06 -0700178 if (device != NULL) {
179 return getScanCodeStateLocked(device, scanCode);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800180 }
181 }
Jeff Brown5c1ed842010-07-14 18:48:53 -0700182 return AKEY_STATE_UNKNOWN;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800183}
184
Jeff Browne839a582010-04-22 18:58:52 -0700185int32_t EventHub::getScanCodeStateLocked(device_t* device, int32_t scanCode) const {
Jeff Brown8575a872010-06-30 16:10:35 -0700186 uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
Jeff Browne839a582010-04-22 18:58:52 -0700187 memset(key_bitmask, 0, sizeof(key_bitmask));
Jens Gulin7dcaa582010-06-22 22:21:57 +0200188 if (ioctl(device->fd,
Jeff Browne839a582010-04-22 18:58:52 -0700189 EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700190 return test_bit(scanCode, key_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
Jeff Browne839a582010-04-22 18:58:52 -0700191 }
Jeff Brown5c1ed842010-07-14 18:48:53 -0700192 return AKEY_STATE_UNKNOWN;
Jeff Browne839a582010-04-22 18:58:52 -0700193}
194
Jeff Browne57e8952010-07-23 21:28:06 -0700195int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
196 AutoMutex _l(mLock);
Jeff Browne839a582010-04-22 18:58:52 -0700197
Jeff Brown2806e382010-10-01 17:46:21 -0700198 device_t* device = getDeviceLocked(deviceId);
Jeff Browne57e8952010-07-23 21:28:06 -0700199 if (device != NULL) {
200 return getKeyCodeStateLocked(device, keyCode);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800201 }
Jeff Brown5c1ed842010-07-14 18:48:53 -0700202 return AKEY_STATE_UNKNOWN;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800203}
204
Jeff Browne839a582010-04-22 18:58:52 -0700205int32_t EventHub::getKeyCodeStateLocked(device_t* device, int32_t keyCode) const {
Jeff Browna3477c82010-11-10 16:03:06 -0800206 if (!device->layoutMap) {
207 return AKEY_STATE_UNKNOWN;
208 }
209
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800210 Vector<int32_t> scanCodes;
Jeff Browna3477c82010-11-10 16:03:06 -0800211 device->layoutMap->findScanCodes(keyCode, &scanCodes);
Jeff Browne839a582010-04-22 18:58:52 -0700212
Jeff Brown8575a872010-06-30 16:10:35 -0700213 uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800214 memset(key_bitmask, 0, sizeof(key_bitmask));
Jens Gulin7dcaa582010-06-22 22:21:57 +0200215 if (ioctl(device->fd, EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800216 #if 0
217 for (size_t i=0; i<=KEY_MAX; i++) {
218 LOGI("(Scan code %d: down=%d)", i, test_bit(i, key_bitmask));
219 }
220 #endif
221 const size_t N = scanCodes.size();
222 for (size_t i=0; i<N && i<=KEY_MAX; i++) {
223 int32_t sc = scanCodes.itemAt(i);
224 //LOGI("Code %d: down=%d", sc, test_bit(sc, key_bitmask));
225 if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, key_bitmask)) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700226 return AKEY_STATE_DOWN;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800227 }
228 }
Jeff Brown5c1ed842010-07-14 18:48:53 -0700229 return AKEY_STATE_UP;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800230 }
Jeff Brown5c1ed842010-07-14 18:48:53 -0700231 return AKEY_STATE_UNKNOWN;
Jeff Browne839a582010-04-22 18:58:52 -0700232}
233
Jeff Browne57e8952010-07-23 21:28:06 -0700234int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
Jeff Browne839a582010-04-22 18:58:52 -0700235#ifdef EV_SW
236 if (sw >= 0 && sw <= SW_MAX) {
237 AutoMutex _l(mLock);
238
Jeff Brown2806e382010-10-01 17:46:21 -0700239 device_t* device = getDeviceLocked(deviceId);
Jeff Browne57e8952010-07-23 21:28:06 -0700240 if (device != NULL) {
241 return getSwitchStateLocked(device, sw);
Jeff Browne839a582010-04-22 18:58:52 -0700242 }
Jeff Browne839a582010-04-22 18:58:52 -0700243 }
244#endif
Jeff Brown5c1ed842010-07-14 18:48:53 -0700245 return AKEY_STATE_UNKNOWN;
Jeff Browne839a582010-04-22 18:58:52 -0700246}
247
248int32_t EventHub::getSwitchStateLocked(device_t* device, int32_t sw) const {
Jeff Brown8575a872010-06-30 16:10:35 -0700249 uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
Jeff Browne839a582010-04-22 18:58:52 -0700250 memset(sw_bitmask, 0, sizeof(sw_bitmask));
Jens Gulin7dcaa582010-06-22 22:21:57 +0200251 if (ioctl(device->fd,
Jeff Browne839a582010-04-22 18:58:52 -0700252 EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700253 return test_bit(sw, sw_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
Jeff Browne839a582010-04-22 18:58:52 -0700254 }
Jeff Brown5c1ed842010-07-14 18:48:53 -0700255 return AKEY_STATE_UNKNOWN;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800256}
257
Jeff Browne57e8952010-07-23 21:28:06 -0700258bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
259 const int32_t* keyCodes, uint8_t* outFlags) const {
260 AutoMutex _l(mLock);
261
Jeff Brown2806e382010-10-01 17:46:21 -0700262 device_t* device = getDeviceLocked(deviceId);
Jeff Browne57e8952010-07-23 21:28:06 -0700263 if (device != NULL) {
264 return markSupportedKeyCodesLocked(device, numCodes, keyCodes, outFlags);
265 }
266 return false;
267}
268
269bool EventHub::markSupportedKeyCodesLocked(device_t* device, size_t numCodes,
270 const int32_t* keyCodes, uint8_t* outFlags) const {
271 if (device->layoutMap == NULL || device->keyBitmask == NULL) {
272 return false;
273 }
274
275 Vector<int32_t> scanCodes;
276 for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
277 scanCodes.clear();
278
Jeff Browna3477c82010-11-10 16:03:06 -0800279 status_t err = device->layoutMap->findScanCodes(keyCodes[codeIndex], &scanCodes);
Jeff Browne57e8952010-07-23 21:28:06 -0700280 if (! err) {
281 // check the possible scan codes identified by the layout map against the
282 // map of codes actually emitted by the driver
283 for (size_t sc = 0; sc < scanCodes.size(); sc++) {
284 if (test_bit(scanCodes[sc], device->keyBitmask)) {
285 outFlags[codeIndex] = 1;
286 break;
287 }
288 }
289 }
290 }
291 return true;
292}
293
Dianne Hackbornc968c3a2009-07-14 12:06:54 -0700294status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode,
295 int32_t* outKeycode, uint32_t* outFlags) const
296{
297 AutoMutex _l(mLock);
Jeff Brown2806e382010-10-01 17:46:21 -0700298 device_t* device = getDeviceLocked(deviceId);
Dianne Hackbornc968c3a2009-07-14 12:06:54 -0700299
300 if (device != NULL && device->layoutMap != NULL) {
301 status_t err = device->layoutMap->map(scancode, outKeycode, outFlags);
302 if (err == NO_ERROR) {
303 return NO_ERROR;
304 }
305 }
306
307 if (mHaveFirstKeyboard) {
Jeff Brown2806e382010-10-01 17:46:21 -0700308 device = getDeviceLocked(mFirstKeyboardId);
Dianne Hackbornc968c3a2009-07-14 12:06:54 -0700309
310 if (device != NULL && device->layoutMap != NULL) {
311 status_t err = device->layoutMap->map(scancode, outKeycode, outFlags);
312 if (err == NO_ERROR) {
313 return NO_ERROR;
314 }
315 }
316 }
317
318 *outKeycode = 0;
319 *outFlags = 0;
320 return NAME_NOT_FOUND;
321}
322
Mike Lockwoodb4411062009-07-16 11:11:18 -0400323void EventHub::addExcludedDevice(const char* deviceName)
324{
Jeff Brown2806e382010-10-01 17:46:21 -0700325 AutoMutex _l(mLock);
326
Mike Lockwoodb4411062009-07-16 11:11:18 -0400327 String8 name(deviceName);
328 mExcludedDevices.push_back(name);
329}
330
Jeff Brown6a817e22010-09-12 17:55:08 -0700331bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
332 AutoMutex _l(mLock);
333 device_t* device = getDeviceLocked(deviceId);
334 if (device) {
335 uint8_t bitmask[sizeof_bit_array(LED_MAX + 1)];
336 memset(bitmask, 0, sizeof(bitmask));
337 if (ioctl(device->fd, EVIOCGBIT(EV_LED, sizeof(bitmask)), bitmask) >= 0) {
338 if (test_bit(led, bitmask)) {
339 return true;
340 }
341 }
342 }
343 return false;
344}
345
346void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) {
347 AutoMutex _l(mLock);
348 device_t* device = getDeviceLocked(deviceId);
349 if (device) {
350 struct input_event ev;
351 ev.time.tv_sec = 0;
352 ev.time.tv_usec = 0;
353 ev.type = EV_LED;
354 ev.code = led;
355 ev.value = on ? 1 : 0;
356
357 ssize_t nWrite;
358 do {
359 nWrite = write(device->fd, &ev, sizeof(struct input_event));
360 } while (nWrite == -1 && errno == EINTR);
361 }
362}
363
Jeff Brown2806e382010-10-01 17:46:21 -0700364EventHub::device_t* EventHub::getDeviceLocked(int32_t deviceId) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800365{
366 if (deviceId == 0) deviceId = mFirstKeyboardId;
367 int32_t id = deviceId & ID_MASK;
368 if (id >= mNumDevicesById || id < 0) return NULL;
369 device_t* dev = mDevicesById[id].device;
Dianne Hackbornc3aa00b2009-03-25 16:21:55 -0700370 if (dev == NULL) return NULL;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800371 if (dev->id == deviceId) {
372 return dev;
373 }
374 return NULL;
375}
376
Jeff Browne57e8952010-07-23 21:28:06 -0700377bool EventHub::getEvent(RawEvent* outEvent)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800378{
Jeff Browne57e8952010-07-23 21:28:06 -0700379 outEvent->deviceId = 0;
380 outEvent->type = 0;
381 outEvent->scanCode = 0;
382 outEvent->keyCode = 0;
383 outEvent->flags = 0;
384 outEvent->value = 0;
385 outEvent->when = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800386
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800387 // Note that we only allow one caller to getEvent(), so don't need
388 // to do locking here... only when adding/removing devices.
Mike Lockwoodb4411062009-07-16 11:11:18 -0400389
390 if (!mOpened) {
391 mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;
392 mOpened = true;
Jeff Brown1ad00e92010-10-01 18:55:43 -0700393 mNeedToSendFinishedDeviceScan = true;
Mike Lockwoodb4411062009-07-16 11:11:18 -0400394 }
395
Jeff Brown82763072010-08-17 16:48:25 -0700396 for (;;) {
397 // Report any devices that had last been added/removed.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800398 if (mClosingDevices != NULL) {
399 device_t* device = mClosingDevices;
400 LOGV("Reporting device closed: id=0x%x, name=%s\n",
401 device->id, device->path.string());
402 mClosingDevices = device->next;
Jeff Browne57e8952010-07-23 21:28:06 -0700403 if (device->id == mFirstKeyboardId) {
404 outEvent->deviceId = 0;
405 } else {
406 outEvent->deviceId = device->id;
407 }
408 outEvent->type = DEVICE_REMOVED;
Jeff Brown3c3cc622010-10-20 15:33:38 -0700409 outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800410 delete device;
Jeff Brown1ad00e92010-10-01 18:55:43 -0700411 mNeedToSendFinishedDeviceScan = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800412 return true;
413 }
Jeff Browne57e8952010-07-23 21:28:06 -0700414
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800415 if (mOpeningDevices != NULL) {
416 device_t* device = mOpeningDevices;
417 LOGV("Reporting device opened: id=0x%x, name=%s\n",
418 device->id, device->path.string());
419 mOpeningDevices = device->next;
Jeff Browne57e8952010-07-23 21:28:06 -0700420 if (device->id == mFirstKeyboardId) {
421 outEvent->deviceId = 0;
422 } else {
423 outEvent->deviceId = device->id;
424 }
425 outEvent->type = DEVICE_ADDED;
Jeff Brown3c3cc622010-10-20 15:33:38 -0700426 outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown1ad00e92010-10-01 18:55:43 -0700427 mNeedToSendFinishedDeviceScan = true;
428 return true;
429 }
430
431 if (mNeedToSendFinishedDeviceScan) {
432 mNeedToSendFinishedDeviceScan = false;
433 outEvent->type = FINISHED_DEVICE_SCAN;
Jeff Brown3c3cc622010-10-20 15:33:38 -0700434 outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800435 return true;
436 }
437
Jeff Brown82763072010-08-17 16:48:25 -0700438 // Grab the next input event.
439 for (;;) {
440 // Consume buffered input events, if any.
441 if (mInputBufferIndex < mInputBufferCount) {
442 const struct input_event& iev = mInputBufferData[mInputBufferIndex++];
443 const device_t* device = mDevices[mInputDeviceIndex];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800444
Jeff Brown82763072010-08-17 16:48:25 -0700445 LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, v=%d", device->path.string(),
446 (int) iev.time.tv_sec, (int) iev.time.tv_usec, iev.type, iev.code, iev.value);
447 if (device->id == mFirstKeyboardId) {
448 outEvent->deviceId = 0;
449 } else {
450 outEvent->deviceId = device->id;
451 }
452 outEvent->type = iev.type;
453 outEvent->scanCode = iev.code;
Jeff Browna3477c82010-11-10 16:03:06 -0800454 outEvent->flags = 0;
Jeff Brown82763072010-08-17 16:48:25 -0700455 if (iev.type == EV_KEY) {
Jeff Browna3477c82010-11-10 16:03:06 -0800456 outEvent->keyCode = AKEYCODE_UNKNOWN;
457 if (device->layoutMap) {
458 status_t err = device->layoutMap->map(iev.code,
459 &outEvent->keyCode, &outEvent->flags);
460 LOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n",
461 iev.code, outEvent->keyCode, outEvent->flags, err);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800462 }
Jeff Brown82763072010-08-17 16:48:25 -0700463 } else {
464 outEvent->keyCode = iev.code;
465 }
466 outEvent->value = iev.value;
467
468 // Use an event timestamp in the same timebase as
469 // java.lang.System.nanoTime() and android.os.SystemClock.uptimeMillis()
470 // as expected by the rest of the system.
471 outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
472 return true;
473 }
474
475 // Finish reading all events from devices identified in previous poll().
476 // This code assumes that mInputDeviceIndex is initially 0 and that the
477 // revents member of pollfd is initialized to 0 when the device is first added.
478 // Since mFDs[0] is used for inotify, we process regular events starting at index 1.
479 mInputDeviceIndex += 1;
480 if (mInputDeviceIndex >= mFDCount) {
Jeff Brown82763072010-08-17 16:48:25 -0700481 break;
482 }
483
Jeff Brown7e40f362010-10-14 02:23:43 -0700484 const struct pollfd& pfd = mFDs[mInputDeviceIndex];
Jeff Brown82763072010-08-17 16:48:25 -0700485 if (pfd.revents & POLLIN) {
486 int32_t readSize = read(pfd.fd, mInputBufferData,
487 sizeof(struct input_event) * INPUT_BUFFER_SIZE);
488 if (readSize < 0) {
489 if (errno != EAGAIN && errno != EINTR) {
490 LOGW("could not get event (errno=%d)", errno);
491 }
492 } else if ((readSize % sizeof(struct input_event)) != 0) {
493 LOGE("could not get event (wrong size: %d)", readSize);
494 } else {
495 mInputBufferCount = readSize / sizeof(struct input_event);
496 mInputBufferIndex = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800497 }
498 }
499 }
Jeff Brown82763072010-08-17 16:48:25 -0700500
Jeff Brown7e40f362010-10-14 02:23:43 -0700501#if HAVE_INOTIFY
Jeff Brown1ad00e92010-10-01 18:55:43 -0700502 // readNotify() will modify mFDs and mFDCount, so this must be done after
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800503 // processing all other events.
504 if(mFDs[0].revents & POLLIN) {
Jeff Brown1ad00e92010-10-01 18:55:43 -0700505 readNotify(mFDs[0].fd);
Jeff Brown7e40f362010-10-14 02:23:43 -0700506 mFDs[0].revents = 0;
507 continue; // report added or removed devices immediately
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800508 }
Jeff Brown7e40f362010-10-14 02:23:43 -0700509#endif
510
511 mInputDeviceIndex = 0;
Jeff Brown82763072010-08-17 16:48:25 -0700512
513 // Poll for events. Mind the wake lock dance!
514 // We hold a wake lock at all times except during poll(). This works due to some
515 // subtle choreography. When a device driver has pending (unread) events, it acquires
516 // a kernel wake lock. However, once the last pending event has been read, the device
517 // driver will release the kernel wake lock. To prevent the system from going to sleep
518 // when this happens, the EventHub holds onto its own user wake lock while the client
519 // is processing events. Thus the system can only sleep if there are no events
520 // pending or currently being processed.
521 release_wake_lock(WAKE_LOCK_ID);
522
523 int pollResult = poll(mFDs, mFDCount, -1);
524
525 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
526
527 if (pollResult <= 0) {
528 if (errno != EINTR) {
Jeff Brown7e40f362010-10-14 02:23:43 -0700529 LOGW("poll failed (errno=%d)\n", errno);
Jeff Brown82763072010-08-17 16:48:25 -0700530 usleep(100000);
531 }
532 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800533 }
534}
535
536/*
537 * Open the platform-specific input device.
538 */
539bool EventHub::openPlatformInput(void)
540{
541 /*
542 * Open platform-specific input device(s).
543 */
544 int res;
545
546 mFDCount = 1;
547 mFDs = (pollfd *)calloc(1, sizeof(mFDs[0]));
548 mDevices = (device_t **)calloc(1, sizeof(mDevices[0]));
549 mFDs[0].events = POLLIN;
Jeff Brown82763072010-08-17 16:48:25 -0700550 mFDs[0].revents = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800551 mDevices[0] = NULL;
552#ifdef HAVE_INOTIFY
553 mFDs[0].fd = inotify_init();
554 res = inotify_add_watch(mFDs[0].fd, device_path, IN_DELETE | IN_CREATE);
555 if(res < 0) {
556 LOGE("could not add watch for %s, %s\n", device_path, strerror(errno));
557 }
558#else
559 /*
560 * The code in EventHub::getEvent assumes that mFDs[0] is an inotify fd.
561 * We allocate space for it and set it to something invalid.
562 */
563 mFDs[0].fd = -1;
564#endif
565
Jeff Brown1ad00e92010-10-01 18:55:43 -0700566 res = scanDir(device_path);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800567 if(res < 0) {
568 LOGE("scan dir failed for %s\n", device_path);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800569 }
570
571 return true;
572}
573
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800574// ----------------------------------------------------------------------------
575
Jeff Brown8575a872010-06-30 16:10:35 -0700576static bool containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex) {
577 const uint8_t* end = array + endIndex;
578 array += startIndex;
579 while (array != end) {
580 if (*(array++) != 0) {
581 return true;
582 }
583 }
584 return false;
585}
586
587static const int32_t GAMEPAD_KEYCODES[] = {
588 AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C,
589 AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z,
590 AKEYCODE_BUTTON_L1, AKEYCODE_BUTTON_R1,
591 AKEYCODE_BUTTON_L2, AKEYCODE_BUTTON_R2,
592 AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR,
593 AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE
594};
595
Jeff Brown1ad00e92010-10-01 18:55:43 -0700596int EventHub::openDevice(const char *deviceName) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800597 int version;
598 int fd;
599 struct pollfd *new_mFDs;
600 device_t **new_devices;
601 char **new_device_names;
602 char name[80];
603 char location[80];
604 char idstr[80];
605 struct input_id id;
606
607 LOGV("Opening device: %s", deviceName);
608
609 AutoMutex _l(mLock);
Nick Pellyc81bb202010-01-20 19:36:49 -0800610
Nick Pelly1b5cf322010-01-26 10:27:15 -0800611 fd = open(deviceName, O_RDWR);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800612 if(fd < 0) {
613 LOGE("could not open %s, %s\n", deviceName, strerror(errno));
614 return -1;
615 }
616
617 if(ioctl(fd, EVIOCGVERSION, &version)) {
618 LOGE("could not get driver version for %s, %s\n", deviceName, strerror(errno));
619 return -1;
620 }
621 if(ioctl(fd, EVIOCGID, &id)) {
622 LOGE("could not get driver id for %s, %s\n", deviceName, strerror(errno));
623 return -1;
624 }
625 name[sizeof(name) - 1] = '\0';
626 location[sizeof(location) - 1] = '\0';
627 idstr[sizeof(idstr) - 1] = '\0';
628 if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
629 //fprintf(stderr, "could not get device name for %s, %s\n", deviceName, strerror(errno));
630 name[0] = '\0';
631 }
Mike Lockwood24a7e042009-07-17 00:10:10 -0400632
633 // check to see if the device is on our excluded list
634 List<String8>::iterator iter = mExcludedDevices.begin();
635 List<String8>::iterator end = mExcludedDevices.end();
636 for ( ; iter != end; iter++) {
637 const char* test = *iter;
638 if (strcmp(name, test) == 0) {
639 LOGI("ignoring event id %s driver %s\n", deviceName, test);
640 close(fd);
Mike Lockwood24a7e042009-07-17 00:10:10 -0400641 return -1;
642 }
643 }
644
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800645 if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) {
646 //fprintf(stderr, "could not get location for %s, %s\n", deviceName, strerror(errno));
647 location[0] = '\0';
648 }
649 if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) {
650 //fprintf(stderr, "could not get idstring for %s, %s\n", deviceName, strerror(errno));
651 idstr[0] = '\0';
652 }
653
Jeff Brown82763072010-08-17 16:48:25 -0700654 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
655 LOGE("Error %d making device file descriptor non-blocking.", errno);
656 close(fd);
657 return -1;
658 }
659
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800660 int devid = 0;
661 while (devid < mNumDevicesById) {
662 if (mDevicesById[devid].device == NULL) {
663 break;
664 }
665 devid++;
666 }
667 if (devid >= mNumDevicesById) {
668 device_ent* new_devids = (device_ent*)realloc(mDevicesById,
669 sizeof(mDevicesById[0]) * (devid + 1));
670 if (new_devids == NULL) {
671 LOGE("out of memory");
672 return -1;
673 }
674 mDevicesById = new_devids;
675 mNumDevicesById = devid+1;
676 mDevicesById[devid].device = NULL;
677 mDevicesById[devid].seq = 0;
678 }
679
680 mDevicesById[devid].seq = (mDevicesById[devid].seq+(1<<SEQ_SHIFT))&SEQ_MASK;
681 if (mDevicesById[devid].seq == 0) {
682 mDevicesById[devid].seq = 1<<SEQ_SHIFT;
683 }
684
685 new_mFDs = (pollfd*)realloc(mFDs, sizeof(mFDs[0]) * (mFDCount + 1));
686 new_devices = (device_t**)realloc(mDevices, sizeof(mDevices[0]) * (mFDCount + 1));
687 if (new_mFDs == NULL || new_devices == NULL) {
688 LOGE("out of memory");
689 return -1;
690 }
691 mFDs = new_mFDs;
692 mDevices = new_devices;
693
694#if 0
695 LOGI("add device %d: %s\n", mFDCount, deviceName);
696 LOGI(" bus: %04x\n"
697 " vendor %04x\n"
698 " product %04x\n"
699 " version %04x\n",
700 id.bustype, id.vendor, id.product, id.version);
701 LOGI(" name: \"%s\"\n", name);
702 LOGI(" location: \"%s\"\n"
703 " id: \"%s\"\n", location, idstr);
704 LOGI(" version: %d.%d.%d\n",
705 version >> 16, (version >> 8) & 0xff, version & 0xff);
706#endif
707
Iliyan Malchev34193b32009-08-06 14:50:08 -0700708 device_t* device = new device_t(devid|mDevicesById[devid].seq, deviceName, name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800709 if (device == NULL) {
710 LOGE("out of memory");
711 return -1;
712 }
713
Jens Gulin7dcaa582010-06-22 22:21:57 +0200714 device->fd = fd;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800715 mFDs[mFDCount].fd = fd;
716 mFDs[mFDCount].events = POLLIN;
Jeff Brown82763072010-08-17 16:48:25 -0700717 mFDs[mFDCount].revents = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800718
Jeff Brown8575a872010-06-30 16:10:35 -0700719 // Figure out the kinds of events the device reports.
Dianne Hackbornc5917362009-08-04 05:49:43 -0700720
Jeff Brown8575a872010-06-30 16:10:35 -0700721 uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800722 memset(key_bitmask, 0, sizeof(key_bitmask));
Jeff Brown8575a872010-06-30 16:10:35 -0700723
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800724 LOGV("Getting keys...");
725 if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
726 //LOGI("MAP\n");
Jeff Brown8575a872010-06-30 16:10:35 -0700727 //for (int i = 0; i < sizeof(key_bitmask); i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800728 // LOGI("%d: 0x%02x\n", i, key_bitmask[i]);
729 //}
Jeff Brown8575a872010-06-30 16:10:35 -0700730
731 // See if this is a keyboard. Ignore everything in the button range except for
732 // gamepads which are also considered keyboards.
733 if (containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC))
734 || containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_GAMEPAD),
735 sizeof_bit_array(BTN_DIGI))
736 || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK),
737 sizeof_bit_array(KEY_MAX + 1))) {
738 device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
739
Dianne Hackbornc5917362009-08-04 05:49:43 -0700740 device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800741 if (device->keyBitmask != NULL) {
742 memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
743 } else {
744 delete device;
745 LOGE("out of memory allocating key bitmask");
746 return -1;
747 }
748 }
749 }
Dianne Hackbornc5917362009-08-04 05:49:43 -0700750
Jeff Brown8575a872010-06-30 16:10:35 -0700751 // See if this is a trackball (or mouse).
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800752 if (test_bit(BTN_MOUSE, key_bitmask)) {
Jeff Brown8575a872010-06-30 16:10:35 -0700753 uint8_t rel_bitmask[sizeof_bit_array(REL_MAX + 1)];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800754 memset(rel_bitmask, 0, sizeof(rel_bitmask));
755 LOGV("Getting relative controllers...");
Jeff Brown8575a872010-06-30 16:10:35 -0700756 if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800757 if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
Jeff Browne839a582010-04-22 18:58:52 -0700758 device->classes |= INPUT_DEVICE_CLASS_TRACKBALL;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800759 }
760 }
761 }
Jeff Brown8575a872010-06-30 16:10:35 -0700762
763 // See if this is a touch pad.
764 uint8_t abs_bitmask[sizeof_bit_array(ABS_MAX + 1)];
Dianne Hackbornc5917362009-08-04 05:49:43 -0700765 memset(abs_bitmask, 0, sizeof(abs_bitmask));
766 LOGV("Getting absolute controllers...");
Jeff Brown8575a872010-06-30 16:10:35 -0700767 if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0) {
768 // Is this a new modern multi-touch driver?
Jeff Brown38a7fab2010-08-30 03:02:23 -0700769 if (test_bit(ABS_MT_POSITION_X, abs_bitmask)
Jeff Brown8575a872010-06-30 16:10:35 -0700770 && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
771 device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT;
772
773 // Is this an old style single-touch driver?
774 } else if (test_bit(BTN_TOUCH, key_bitmask)
775 && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
776 device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN;
777 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800778 }
779
780#ifdef EV_SW
781 // figure out the switches this device reports
Jeff Brown8575a872010-06-30 16:10:35 -0700782 uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800783 memset(sw_bitmask, 0, sizeof(sw_bitmask));
Jeff Browne57e8952010-07-23 21:28:06 -0700784 bool hasSwitches = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800785 if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
786 for (int i=0; i<EV_SW; i++) {
787 //LOGI("Device 0x%x sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
788 if (test_bit(i, sw_bitmask)) {
Jeff Browne57e8952010-07-23 21:28:06 -0700789 hasSwitches = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800790 if (mSwitches[i] == 0) {
791 mSwitches[i] = device->id;
792 }
793 }
794 }
795 }
Jeff Browne57e8952010-07-23 21:28:06 -0700796 if (hasSwitches) {
797 device->classes |= INPUT_DEVICE_CLASS_SWITCH;
798 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800799#endif
800
Jeff Browne839a582010-04-22 18:58:52 -0700801 if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800802 // a more descriptive name
Iliyan Malchev34193b32009-08-06 14:50:08 -0700803 device->name = name;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800804
Jeff Brown6a817e22010-09-12 17:55:08 -0700805 // Configure the keymap for the device.
Jeff Browna3477c82010-11-10 16:03:06 -0800806
Jeff Brown6a817e22010-09-12 17:55:08 -0700807 configureKeyMap(device);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800808
Jeff Brown6a817e22010-09-12 17:55:08 -0700809 // Tell the world about the devname (the descriptive name)
Jeff Browna3477c82010-11-10 16:03:06 -0800810 if (!mHaveFirstKeyboard && !device->keyMapInfo.isDefaultKeyMap && strstr(name, "-keypad")) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800811 // the built-in keyboard has a well-known device ID of 0,
812 // this device better not go away.
813 mHaveFirstKeyboard = true;
814 mFirstKeyboardId = device->id;
Jeff Brown6a817e22010-09-12 17:55:08 -0700815 setKeyboardProperties(device, true);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800816 } else {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800817 // ensure mFirstKeyboardId is set to -something-.
Jeff Brown6a817e22010-09-12 17:55:08 -0700818 if (mFirstKeyboardId == -1) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800819 mFirstKeyboardId = device->id;
Jeff Brown6a817e22010-09-12 17:55:08 -0700820 setKeyboardProperties(device, true);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800821 }
822 }
Jeff Brown6a817e22010-09-12 17:55:08 -0700823 setKeyboardProperties(device, false);
824
825 // Load the keylayout.
Jeff Browna3477c82010-11-10 16:03:06 -0800826 if (!device->keyMapInfo.keyLayoutFile.isEmpty()) {
827 status_t status = KeyLayoutMap::load(device->keyMapInfo.keyLayoutFile,
828 &device->layoutMap);
Jeff Brown6a817e22010-09-12 17:55:08 -0700829 if (status) {
830 LOGE("Error %d loading key layout file '%s'.", status,
Jeff Browna3477c82010-11-10 16:03:06 -0800831 device->keyMapInfo.keyLayoutFile.string());
Jeff Brown6a817e22010-09-12 17:55:08 -0700832 }
833 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800834
Dianne Hackbornc5917362009-08-04 05:49:43 -0700835 // 'Q' key support = cheap test of whether this is an alpha-capable kbd
Jeff Brown2806e382010-10-01 17:46:21 -0700836 if (hasKeycodeLocked(device, AKEYCODE_Q)) {
Jeff Browne839a582010-04-22 18:58:52 -0700837 device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
Dianne Hackbornc5917362009-08-04 05:49:43 -0700838 }
Jeff Brown6a817e22010-09-12 17:55:08 -0700839
Jeff Brown8575a872010-06-30 16:10:35 -0700840 // See if this device has a DPAD.
Jeff Brown2806e382010-10-01 17:46:21 -0700841 if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
842 hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
843 hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
844 hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
845 hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
Jeff Browne839a582010-04-22 18:58:52 -0700846 device->classes |= INPUT_DEVICE_CLASS_DPAD;
Dianne Hackbornc5917362009-08-04 05:49:43 -0700847 }
Jeff Brown6a817e22010-09-12 17:55:08 -0700848
Jeff Brown8575a872010-06-30 16:10:35 -0700849 // See if this device has a gamepad.
Kenny Rootbc9c82f2010-10-21 15:46:03 -0700850 for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {
Jeff Brown2806e382010-10-01 17:46:21 -0700851 if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
Jeff Brown8575a872010-06-30 16:10:35 -0700852 device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
853 break;
854 }
855 }
856
Jeff Brown6a817e22010-09-12 17:55:08 -0700857 LOGI("New keyboard: device->id=0x%x devname='%s' keylayout='%s' keycharactermap='%s'\n",
858 device->id, name,
Jeff Browna3477c82010-11-10 16:03:06 -0800859 device->keyMapInfo.keyLayoutFile.string(),
860 device->keyMapInfo.keyCharacterMapFile.string());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800861 }
862
Sean McNeil2e7a5302010-06-23 16:00:37 +0700863 // If the device isn't recognized as something we handle, don't monitor it.
864 if (device->classes == 0) {
865 LOGV("Dropping device %s %p, id = %d\n", deviceName, device, devid);
866 close(fd);
867 delete device;
868 return -1;
869 }
870
Dianne Hackbornc5917362009-08-04 05:49:43 -0700871 LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
872 deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes);
873
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800874 LOGV("Adding device %s %p at %d, id = %d, classes = 0x%x\n",
875 deviceName, device, mFDCount, devid, device->classes);
876
877 mDevicesById[devid].device = device;
878 device->next = mOpeningDevices;
879 mOpeningDevices = device;
880 mDevices[mFDCount] = device;
881
882 mFDCount++;
883 return 0;
884}
885
Jeff Brown6a817e22010-09-12 17:55:08 -0700886void EventHub::configureKeyMap(device_t* device) {
Jeff Browna3477c82010-11-10 16:03:06 -0800887 android::resolveKeyMap(device->name, device->keyMapInfo);
Jeff Brown6a817e22010-09-12 17:55:08 -0700888}
889
890void EventHub::setKeyboardProperties(device_t* device, bool firstKeyboard) {
891 int32_t id = firstKeyboard ? 0 : device->id;
Jeff Browna3477c82010-11-10 16:03:06 -0800892 android::setKeyboardProperties(id, device->name, device->keyMapInfo);
Jeff Brown6a817e22010-09-12 17:55:08 -0700893}
894
895void EventHub::clearKeyboardProperties(device_t* device, bool firstKeyboard) {
896 int32_t id = firstKeyboard ? 0 : device->id;
Jeff Browna3477c82010-11-10 16:03:06 -0800897 android::clearKeyboardProperties(id);
Jeff Brown6a817e22010-09-12 17:55:08 -0700898}
899
Jeff Brown2806e382010-10-01 17:46:21 -0700900bool EventHub::hasKeycodeLocked(device_t* device, int keycode) const
Dianne Hackbornc5917362009-08-04 05:49:43 -0700901{
902 if (device->keyBitmask == NULL || device->layoutMap == NULL) {
903 return false;
904 }
905
906 Vector<int32_t> scanCodes;
Jeff Browna3477c82010-11-10 16:03:06 -0800907 device->layoutMap->findScanCodes(keycode, &scanCodes);
Dianne Hackbornc5917362009-08-04 05:49:43 -0700908 const size_t N = scanCodes.size();
909 for (size_t i=0; i<N && i<=KEY_MAX; i++) {
910 int32_t sc = scanCodes.itemAt(i);
911 if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) {
912 return true;
913 }
914 }
915
916 return false;
917}
918
Jeff Brown1ad00e92010-10-01 18:55:43 -0700919int EventHub::closeDevice(const char *deviceName) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800920 AutoMutex _l(mLock);
Jeff Brown1ad00e92010-10-01 18:55:43 -0700921
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800922 int i;
923 for(i = 1; i < mFDCount; i++) {
924 if(strcmp(mDevices[i]->path.string(), deviceName) == 0) {
925 //LOGD("remove device %d: %s\n", i, deviceName);
926 device_t* device = mDevices[i];
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700927
928 LOGI("Removed device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
929 device->path.string(), device->name.string(), device->id,
930 mNumDevicesById, mFDCount, mFDs[i].fd, device->classes);
931
932 // Clear this device's entry.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800933 int index = (device->id&ID_MASK);
934 mDevicesById[index].device = NULL;
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700935
936 // Close the file descriptor and compact the fd array.
Mike Lockwood07549f92009-08-28 13:29:06 -0700937 close(mFDs[i].fd);
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700938 int count = mFDCount - i - 1;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800939 memmove(mDevices + i, mDevices + i + 1, sizeof(mDevices[0]) * count);
940 memmove(mFDs + i, mFDs + i + 1, sizeof(mFDs[0]) * count);
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700941 mFDCount--;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800942
943#ifdef EV_SW
944 for (int j=0; j<EV_SW; j++) {
945 if (mSwitches[j] == device->id) {
946 mSwitches[j] = 0;
947 }
948 }
949#endif
950
951 device->next = mClosingDevices;
952 mClosingDevices = device;
953
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800954 if (device->id == mFirstKeyboardId) {
955 LOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
956 device->path.string(), mFirstKeyboardId);
Jeff Brown6a817e22010-09-12 17:55:08 -0700957 mFirstKeyboardId = -1;
958 clearKeyboardProperties(device, true);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800959 }
Jeff Brown6a817e22010-09-12 17:55:08 -0700960 clearKeyboardProperties(device, false);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800961 return 0;
962 }
963 }
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700964 LOGE("remove device: %s not found\n", deviceName);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800965 return -1;
966}
967
Jeff Brown1ad00e92010-10-01 18:55:43 -0700968int EventHub::readNotify(int nfd) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800969#ifdef HAVE_INOTIFY
970 int res;
971 char devname[PATH_MAX];
972 char *filename;
973 char event_buf[512];
974 int event_size;
975 int event_pos = 0;
976 struct inotify_event *event;
977
Jeff Brown1ad00e92010-10-01 18:55:43 -0700978 LOGV("EventHub::readNotify nfd: %d\n", nfd);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800979 res = read(nfd, event_buf, sizeof(event_buf));
980 if(res < (int)sizeof(*event)) {
981 if(errno == EINTR)
982 return 0;
983 LOGW("could not get event, %s\n", strerror(errno));
984 return 1;
985 }
986 //printf("got %d bytes of event information\n", res);
987
988 strcpy(devname, device_path);
989 filename = devname + strlen(devname);
990 *filename++ = '/';
991
992 while(res >= (int)sizeof(*event)) {
993 event = (struct inotify_event *)(event_buf + event_pos);
994 //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");
995 if(event->len) {
996 strcpy(filename, event->name);
997 if(event->mask & IN_CREATE) {
Jeff Brown1ad00e92010-10-01 18:55:43 -0700998 openDevice(devname);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800999 }
1000 else {
Jeff Brown1ad00e92010-10-01 18:55:43 -07001001 closeDevice(devname);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001002 }
1003 }
1004 event_size = sizeof(*event) + event->len;
1005 res -= event_size;
1006 event_pos += event_size;
1007 }
1008#endif
1009 return 0;
1010}
1011
1012
Jeff Brown1ad00e92010-10-01 18:55:43 -07001013int EventHub::scanDir(const char *dirname)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001014{
1015 char devname[PATH_MAX];
1016 char *filename;
1017 DIR *dir;
1018 struct dirent *de;
1019 dir = opendir(dirname);
1020 if(dir == NULL)
1021 return -1;
1022 strcpy(devname, dirname);
1023 filename = devname + strlen(devname);
1024 *filename++ = '/';
1025 while((de = readdir(dir))) {
1026 if(de->d_name[0] == '.' &&
1027 (de->d_name[1] == '\0' ||
1028 (de->d_name[1] == '.' && de->d_name[2] == '\0')))
1029 continue;
1030 strcpy(filename, de->d_name);
Jeff Brown1ad00e92010-10-01 18:55:43 -07001031 openDevice(devname);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001032 }
1033 closedir(dir);
1034 return 0;
1035}
1036
Jeff Brown2806e382010-10-01 17:46:21 -07001037void EventHub::dump(String8& dump) {
1038 dump.append("Event Hub State:\n");
1039
1040 { // acquire lock
1041 AutoMutex _l(mLock);
1042
1043 dump.appendFormat(INDENT "HaveFirstKeyboard: %s\n", toString(mHaveFirstKeyboard));
1044 dump.appendFormat(INDENT "FirstKeyboardId: 0x%x\n", mFirstKeyboardId);
1045
1046 dump.append(INDENT "Devices:\n");
1047
1048 for (int i = 0; i < mNumDevicesById; i++) {
1049 const device_t* device = mDevicesById[i].device;
1050 if (device) {
1051 if (mFirstKeyboardId == device->id) {
1052 dump.appendFormat(INDENT2 "0x%x: %s (aka device 0 - first keyboard)\n",
1053 device->id, device->name.string());
1054 } else {
1055 dump.appendFormat(INDENT2 "0x%x: %s\n", device->id, device->name.string());
1056 }
1057 dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes);
1058 dump.appendFormat(INDENT3 "Path: %s\n", device->path.string());
Jeff Browna3477c82010-11-10 16:03:06 -08001059 dump.appendFormat(INDENT3 "IsDefaultKeyMap: %s\n",
1060 toString(device->keyMapInfo.isDefaultKeyMap));
1061 dump.appendFormat(INDENT3 "KeyMapName: %s\n",
1062 device->keyMapInfo.keyMapName.string());
1063 dump.appendFormat(INDENT3 "KeyLayoutFile: %s\n",
1064 device->keyMapInfo.keyLayoutFile.string());
1065 dump.appendFormat(INDENT3 "KeyCharacterMapFile: %s\n",
1066 device->keyMapInfo.keyCharacterMapFile.string());
Jeff Brown2806e382010-10-01 17:46:21 -07001067 }
1068 }
1069 } // release lock
1070}
1071
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001072}; // namespace android