blob: 27895f2842f93c7203a4ea42e478ff7cd3b2e65b [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>
Dianne Hackbornc5917362009-08-04 05:49:43 -070019#include <ui/KeycodeLabels.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080020#include <hardware_legacy/power.h>
21
22#include <cutils/properties.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080023#include <utils/Log.h>
24#include <utils/Timers.h>
Mathias Agopiane0c32202009-05-31 19:13:00 -070025#include <utils/threads.h>
Mathias Agopiane0c32202009-05-31 19:13:00 -070026#include <utils/Errors.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080027
28#include <stdlib.h>
29#include <stdio.h>
30#include <unistd.h>
31#include <fcntl.h>
32#include <memory.h>
33#include <errno.h>
34#include <assert.h>
35
36#include "KeyLayoutMap.h"
37
38#include <string.h>
39#include <stdint.h>
40#include <dirent.h>
41#ifdef HAVE_INOTIFY
42# include <sys/inotify.h>
43#endif
44#ifdef HAVE_ANDROID_OS
45# include <sys/limits.h> /* not part of Linux */
46#endif
47#include <sys/poll.h>
48#include <sys/ioctl.h>
49
50/* this macro is used to tell if "bit" is set in "array"
51 * it selects a byte from the array, and does a boolean AND
52 * operation with a byte that only has the relevant bit set.
53 * eg. to check for the 12th bit, we do (array[1] & 1<<4)
54 */
55#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8)))
56
57#define ID_MASK 0x0000ffff
58#define SEQ_MASK 0x7fff0000
59#define SEQ_SHIFT 16
60#define id_to_index(id) ((id&ID_MASK)+1)
61
Dianne Hackbornc5917362009-08-04 05:49:43 -070062#ifndef ABS_MT_TOUCH_MAJOR
63#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
64#endif
65
66#ifndef ABS_MT_POSITION_X
67#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
68#endif
69
70#ifndef ABS_MT_POSITION_Y
71#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
72#endif
73
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080074namespace android {
75
76static const char *WAKE_LOCK_ID = "KeyEvents";
77static const char *device_path = "/dev/input";
78
79/* return the larger integer */
80static inline int max(int v1, int v2)
81{
82 return (v1 > v2) ? v1 : v2;
83}
84
Iliyan Malchev34193b32009-08-06 14:50:08 -070085EventHub::device_t::device_t(int32_t _id, const char* _path, const char* name)
86 : id(_id), path(_path), name(name), classes(0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080087 , keyBitmask(NULL), layoutMap(new KeyLayoutMap()), next(NULL) {
88}
89
90EventHub::device_t::~device_t() {
91 delete [] keyBitmask;
92 delete layoutMap;
93}
94
95EventHub::EventHub(void)
96 : mError(NO_INIT), mHaveFirstKeyboard(false), mFirstKeyboardId(0)
97 , mDevicesById(0), mNumDevicesById(0)
98 , mOpeningDevices(0), mClosingDevices(0)
Mike Lockwoodb4411062009-07-16 11:11:18 -040099 , mDevices(0), mFDs(0), mFDCount(0), mOpened(false)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800100{
101 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
102#ifdef EV_SW
103 memset(mSwitches, 0, sizeof(mSwitches));
104#endif
105}
106
107/*
108 * Clean up.
109 */
110EventHub::~EventHub(void)
111{
112 release_wake_lock(WAKE_LOCK_ID);
113 // we should free stuff here...
114}
115
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800116status_t EventHub::errorCheck() const
117{
118 return mError;
119}
120
121String8 EventHub::getDeviceName(int32_t deviceId) const
122{
123 AutoMutex _l(mLock);
124 device_t* device = getDevice(deviceId);
125 if (device == NULL) return String8();
126 return device->name;
127}
128
129uint32_t EventHub::getDeviceClasses(int32_t deviceId) const
130{
131 AutoMutex _l(mLock);
132 device_t* device = getDevice(deviceId);
133 if (device == NULL) return 0;
134 return device->classes;
135}
136
137int EventHub::getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue,
138 int* outMaxValue, int* outFlat, int* outFuzz) const
139{
140 AutoMutex _l(mLock);
141 device_t* device = getDevice(deviceId);
142 if (device == NULL) return -1;
143
144 struct input_absinfo info;
145
146 if(ioctl(mFDs[id_to_index(device->id)].fd, EVIOCGABS(axis), &info)) {
147 LOGE("Error reading absolute controller %d for device %s fd %d\n",
148 axis, device->name.string(), mFDs[id_to_index(device->id)].fd);
149 return -1;
150 }
151 *outMinValue = info.minimum;
152 *outMaxValue = info.maximum;
153 *outFlat = info.flat;
154 *outFuzz = info.fuzz;
155 return 0;
156}
157
Jeff Browne839a582010-04-22 18:58:52 -0700158int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t deviceClasses,
159 int32_t scanCode) const {
160 if (scanCode >= 0 && scanCode <= KEY_MAX) {
161 AutoMutex _l(mLock);
162
163 if (deviceId == -1) {
164 for (int i = 0; i < mNumDevicesById; i++) {
165 device_t* device = mDevicesById[i].device;
166 if (device != NULL && (device->classes & deviceClasses) != 0) {
167 int32_t result = getScanCodeStateLocked(device, scanCode);
168 if (result >= KEY_STATE_DOWN) {
169 return result;
170 }
171 }
172 }
173 return KEY_STATE_UP;
174 } else {
175 device_t* device = getDevice(deviceId);
176 if (device != NULL) {
177 return getScanCodeStateLocked(device, scanCode);
178 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800179 }
180 }
Jeff Browne839a582010-04-22 18:58:52 -0700181 return KEY_STATE_UNKNOWN;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800182}
183
Jeff Browne839a582010-04-22 18:58:52 -0700184int32_t EventHub::getScanCodeStateLocked(device_t* device, int32_t scanCode) const {
185 uint8_t key_bitmask[(KEY_MAX + 7) / 8];
186 memset(key_bitmask, 0, sizeof(key_bitmask));
187 if (ioctl(mFDs[id_to_index(device->id)].fd,
188 EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
189 return test_bit(scanCode, key_bitmask) ? KEY_STATE_DOWN : KEY_STATE_UP;
190 }
191 return KEY_STATE_UNKNOWN;
192}
193
194int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
195 int32_t keyCode) const {
196
197 if (deviceId == -1) {
198 for (int i = 0; i < mNumDevicesById; i++) {
199 device_t* device = mDevicesById[i].device;
200 if (device != NULL && (device->classes & deviceClasses) != 0) {
201 int32_t result = getKeyCodeStateLocked(device, keyCode);
202 if (result >= KEY_STATE_DOWN) {
203 return result;
204 }
205 }
206 }
207 return KEY_STATE_UP;
208 } else {
209 device_t* device = getDevice(deviceId);
210 if (device != NULL) {
211 return getKeyCodeStateLocked(device, keyCode);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800212 }
213 }
Jeff Browne839a582010-04-22 18:58:52 -0700214 return KEY_STATE_UNKNOWN;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800215}
216
Jeff Browne839a582010-04-22 18:58:52 -0700217int32_t EventHub::getKeyCodeStateLocked(device_t* device, int32_t keyCode) const {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800218 Vector<int32_t> scanCodes;
Jeff Browne839a582010-04-22 18:58:52 -0700219 device->layoutMap->findScancodes(keyCode, &scanCodes);
220
221 uint8_t key_bitmask[(KEY_MAX + 7) / 8];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800222 memset(key_bitmask, 0, sizeof(key_bitmask));
223 if (ioctl(mFDs[id_to_index(device->id)].fd,
224 EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
225 #if 0
226 for (size_t i=0; i<=KEY_MAX; i++) {
227 LOGI("(Scan code %d: down=%d)", i, test_bit(i, key_bitmask));
228 }
229 #endif
230 const size_t N = scanCodes.size();
231 for (size_t i=0; i<N && i<=KEY_MAX; i++) {
232 int32_t sc = scanCodes.itemAt(i);
233 //LOGI("Code %d: down=%d", sc, test_bit(sc, key_bitmask));
234 if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, key_bitmask)) {
Jeff Browne839a582010-04-22 18:58:52 -0700235 return KEY_STATE_DOWN;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800236 }
237 }
Jeff Browne839a582010-04-22 18:58:52 -0700238 return KEY_STATE_UP;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800239 }
Jeff Browne839a582010-04-22 18:58:52 -0700240 return KEY_STATE_UNKNOWN;
241}
242
243int32_t EventHub::getSwitchState(int32_t deviceId, int32_t deviceClasses, int32_t sw) const {
244#ifdef EV_SW
245 if (sw >= 0 && sw <= SW_MAX) {
246 AutoMutex _l(mLock);
247
248 if (deviceId == -1) {
249 deviceId = mSwitches[sw];
250 if (deviceId == 0) {
251 return KEY_STATE_UNKNOWN;
252 }
253 }
254
255 device_t* device = getDevice(deviceId);
256 if (device == NULL) {
257 return KEY_STATE_UNKNOWN;
258 }
259
260 return getSwitchStateLocked(device, sw);
261 }
262#endif
263 return KEY_STATE_UNKNOWN;
264}
265
266int32_t EventHub::getSwitchStateLocked(device_t* device, int32_t sw) const {
267 uint8_t sw_bitmask[(SW_MAX + 7) / 8];
268 memset(sw_bitmask, 0, sizeof(sw_bitmask));
269 if (ioctl(mFDs[id_to_index(device->id)].fd,
270 EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) {
271 return test_bit(sw, sw_bitmask) ? KEY_STATE_DOWN : KEY_STATE_UP;
272 }
273 return KEY_STATE_UNKNOWN;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800274}
275
Dianne Hackbornc968c3a2009-07-14 12:06:54 -0700276status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode,
277 int32_t* outKeycode, uint32_t* outFlags) const
278{
279 AutoMutex _l(mLock);
280 device_t* device = getDevice(deviceId);
281
282 if (device != NULL && device->layoutMap != NULL) {
283 status_t err = device->layoutMap->map(scancode, outKeycode, outFlags);
284 if (err == NO_ERROR) {
285 return NO_ERROR;
286 }
287 }
288
289 if (mHaveFirstKeyboard) {
290 device = getDevice(mFirstKeyboardId);
291
292 if (device != NULL && device->layoutMap != NULL) {
293 status_t err = device->layoutMap->map(scancode, outKeycode, outFlags);
294 if (err == NO_ERROR) {
295 return NO_ERROR;
296 }
297 }
298 }
299
300 *outKeycode = 0;
301 *outFlags = 0;
302 return NAME_NOT_FOUND;
303}
304
Mike Lockwoodb4411062009-07-16 11:11:18 -0400305void EventHub::addExcludedDevice(const char* deviceName)
306{
307 String8 name(deviceName);
308 mExcludedDevices.push_back(name);
309}
310
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800311EventHub::device_t* EventHub::getDevice(int32_t deviceId) const
312{
313 if (deviceId == 0) deviceId = mFirstKeyboardId;
314 int32_t id = deviceId & ID_MASK;
315 if (id >= mNumDevicesById || id < 0) return NULL;
316 device_t* dev = mDevicesById[id].device;
Dianne Hackbornc3aa00b2009-03-25 16:21:55 -0700317 if (dev == NULL) return NULL;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800318 if (dev->id == deviceId) {
319 return dev;
320 }
321 return NULL;
322}
323
324bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType,
325 int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags,
326 int32_t* outValue, nsecs_t* outWhen)
327{
328 *outDeviceId = 0;
329 *outType = 0;
330 *outScancode = 0;
331 *outKeycode = 0;
332 *outFlags = 0;
333 *outValue = 0;
334 *outWhen = 0;
335
336 status_t err;
337
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800338 int i;
339 int res;
340 int pollres;
341 struct input_event iev;
342
343 // Note that we only allow one caller to getEvent(), so don't need
344 // to do locking here... only when adding/removing devices.
Mike Lockwoodb4411062009-07-16 11:11:18 -0400345
346 if (!mOpened) {
347 mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;
348 mOpened = true;
349 }
350
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800351 while(1) {
352
353 // First, report any devices that had last been added/removed.
354 if (mClosingDevices != NULL) {
355 device_t* device = mClosingDevices;
356 LOGV("Reporting device closed: id=0x%x, name=%s\n",
357 device->id, device->path.string());
358 mClosingDevices = device->next;
359 *outDeviceId = device->id;
360 if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0;
361 *outType = DEVICE_REMOVED;
362 delete device;
363 return true;
364 }
365 if (mOpeningDevices != NULL) {
366 device_t* device = mOpeningDevices;
367 LOGV("Reporting device opened: id=0x%x, name=%s\n",
368 device->id, device->path.string());
369 mOpeningDevices = device->next;
370 *outDeviceId = device->id;
371 if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0;
372 *outType = DEVICE_ADDED;
373 return true;
374 }
375
376 release_wake_lock(WAKE_LOCK_ID);
377
378 pollres = poll(mFDs, mFDCount, -1);
379
380 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
381
382 if (pollres <= 0) {
383 if (errno != EINTR) {
384 LOGW("select failed (errno=%d)\n", errno);
385 usleep(100000);
386 }
387 continue;
388 }
389
390 //printf("poll %d, returned %d\n", mFDCount, pollres);
391
392 // mFDs[0] is used for inotify, so process regular events starting at mFDs[1]
393 for(i = 1; i < mFDCount; i++) {
394 if(mFDs[i].revents) {
395 LOGV("revents for %d = 0x%08x", i, mFDs[i].revents);
396 if(mFDs[i].revents & POLLIN) {
397 res = read(mFDs[i].fd, &iev, sizeof(iev));
398 if (res == sizeof(iev)) {
399 LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, v=%d",
400 mDevices[i]->path.string(),
401 (int) iev.time.tv_sec, (int) iev.time.tv_usec,
402 iev.type, iev.code, iev.value);
403 *outDeviceId = mDevices[i]->id;
404 if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0;
405 *outType = iev.type;
406 *outScancode = iev.code;
407 if (iev.type == EV_KEY) {
408 err = mDevices[i]->layoutMap->map(iev.code, outKeycode, outFlags);
409 LOGV("iev.code=%d outKeycode=%d outFlags=0x%08x err=%d\n",
410 iev.code, *outKeycode, *outFlags, err);
411 if (err != 0) {
412 *outKeycode = 0;
413 *outFlags = 0;
414 }
415 } else {
416 *outKeycode = iev.code;
417 }
418 *outValue = iev.value;
419 *outWhen = s2ns(iev.time.tv_sec) + us2ns(iev.time.tv_usec);
420 return true;
421 } else {
422 if (res<0) {
423 LOGW("could not get event (errno=%d)", errno);
424 } else {
425 LOGE("could not get event (wrong size: %d)", res);
426 }
427 continue;
428 }
429 }
430 }
431 }
432
433 // read_notify() will modify mFDs and mFDCount, so this must be done after
434 // processing all other events.
435 if(mFDs[0].revents & POLLIN) {
436 read_notify(mFDs[0].fd);
437 }
438 }
439}
440
441/*
442 * Open the platform-specific input device.
443 */
444bool EventHub::openPlatformInput(void)
445{
446 /*
447 * Open platform-specific input device(s).
448 */
449 int res;
450
451 mFDCount = 1;
452 mFDs = (pollfd *)calloc(1, sizeof(mFDs[0]));
453 mDevices = (device_t **)calloc(1, sizeof(mDevices[0]));
454 mFDs[0].events = POLLIN;
455 mDevices[0] = NULL;
456#ifdef HAVE_INOTIFY
457 mFDs[0].fd = inotify_init();
458 res = inotify_add_watch(mFDs[0].fd, device_path, IN_DELETE | IN_CREATE);
459 if(res < 0) {
460 LOGE("could not add watch for %s, %s\n", device_path, strerror(errno));
461 }
462#else
463 /*
464 * The code in EventHub::getEvent assumes that mFDs[0] is an inotify fd.
465 * We allocate space for it and set it to something invalid.
466 */
467 mFDs[0].fd = -1;
468#endif
469
470 res = scan_dir(device_path);
471 if(res < 0) {
472 LOGE("scan dir failed for %s\n", device_path);
473 //open_device("/dev/input/event0");
474 }
475
476 return true;
477}
478
479/*
480 * Inspect the known devices to determine whether physical keys exist for the given
481 * framework-domain key codes.
482 */
Jeff Browne839a582010-04-22 18:58:52 -0700483bool EventHub::hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800484 for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
485 outFlags[codeIndex] = 0;
486
487 // check each available hardware device for support for this keycode
488 Vector<int32_t> scanCodes;
489 for (int n = 0; (n < mFDCount) && (outFlags[codeIndex] == 0); n++) {
490 if (mDevices[n]) {
Jeff Browne839a582010-04-22 18:58:52 -0700491 status_t err = mDevices[n]->layoutMap->findScancodes(
492 keyCodes[codeIndex], &scanCodes);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800493 if (!err) {
494 // check the possible scan codes identified by the layout map against the
495 // map of codes actually emitted by the driver
496 for (size_t sc = 0; sc < scanCodes.size(); sc++) {
497 if (test_bit(scanCodes[sc], mDevices[n]->keyBitmask)) {
498 outFlags[codeIndex] = 1;
499 break;
500 }
501 }
502 }
503 }
504 }
505 }
506
507 return true;
508}
509
510// ----------------------------------------------------------------------------
511
512int EventHub::open_device(const char *deviceName)
513{
514 int version;
515 int fd;
516 struct pollfd *new_mFDs;
517 device_t **new_devices;
518 char **new_device_names;
519 char name[80];
520 char location[80];
521 char idstr[80];
522 struct input_id id;
523
524 LOGV("Opening device: %s", deviceName);
525
526 AutoMutex _l(mLock);
Nick Pellyc81bb202010-01-20 19:36:49 -0800527
Nick Pelly1b5cf322010-01-26 10:27:15 -0800528 fd = open(deviceName, O_RDWR);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800529 if(fd < 0) {
530 LOGE("could not open %s, %s\n", deviceName, strerror(errno));
531 return -1;
532 }
533
534 if(ioctl(fd, EVIOCGVERSION, &version)) {
535 LOGE("could not get driver version for %s, %s\n", deviceName, strerror(errno));
536 return -1;
537 }
538 if(ioctl(fd, EVIOCGID, &id)) {
539 LOGE("could not get driver id for %s, %s\n", deviceName, strerror(errno));
540 return -1;
541 }
542 name[sizeof(name) - 1] = '\0';
543 location[sizeof(location) - 1] = '\0';
544 idstr[sizeof(idstr) - 1] = '\0';
545 if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
546 //fprintf(stderr, "could not get device name for %s, %s\n", deviceName, strerror(errno));
547 name[0] = '\0';
548 }
Mike Lockwood24a7e042009-07-17 00:10:10 -0400549
550 // check to see if the device is on our excluded list
551 List<String8>::iterator iter = mExcludedDevices.begin();
552 List<String8>::iterator end = mExcludedDevices.end();
553 for ( ; iter != end; iter++) {
554 const char* test = *iter;
555 if (strcmp(name, test) == 0) {
556 LOGI("ignoring event id %s driver %s\n", deviceName, test);
557 close(fd);
558 fd = -1;
559 return -1;
560 }
561 }
562
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800563 if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) {
564 //fprintf(stderr, "could not get location for %s, %s\n", deviceName, strerror(errno));
565 location[0] = '\0';
566 }
567 if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) {
568 //fprintf(stderr, "could not get idstring for %s, %s\n", deviceName, strerror(errno));
569 idstr[0] = '\0';
570 }
571
572 int devid = 0;
573 while (devid < mNumDevicesById) {
574 if (mDevicesById[devid].device == NULL) {
575 break;
576 }
577 devid++;
578 }
579 if (devid >= mNumDevicesById) {
580 device_ent* new_devids = (device_ent*)realloc(mDevicesById,
581 sizeof(mDevicesById[0]) * (devid + 1));
582 if (new_devids == NULL) {
583 LOGE("out of memory");
584 return -1;
585 }
586 mDevicesById = new_devids;
587 mNumDevicesById = devid+1;
588 mDevicesById[devid].device = NULL;
589 mDevicesById[devid].seq = 0;
590 }
591
592 mDevicesById[devid].seq = (mDevicesById[devid].seq+(1<<SEQ_SHIFT))&SEQ_MASK;
593 if (mDevicesById[devid].seq == 0) {
594 mDevicesById[devid].seq = 1<<SEQ_SHIFT;
595 }
596
597 new_mFDs = (pollfd*)realloc(mFDs, sizeof(mFDs[0]) * (mFDCount + 1));
598 new_devices = (device_t**)realloc(mDevices, sizeof(mDevices[0]) * (mFDCount + 1));
599 if (new_mFDs == NULL || new_devices == NULL) {
600 LOGE("out of memory");
601 return -1;
602 }
603 mFDs = new_mFDs;
604 mDevices = new_devices;
605
606#if 0
607 LOGI("add device %d: %s\n", mFDCount, deviceName);
608 LOGI(" bus: %04x\n"
609 " vendor %04x\n"
610 " product %04x\n"
611 " version %04x\n",
612 id.bustype, id.vendor, id.product, id.version);
613 LOGI(" name: \"%s\"\n", name);
614 LOGI(" location: \"%s\"\n"
615 " id: \"%s\"\n", location, idstr);
616 LOGI(" version: %d.%d.%d\n",
617 version >> 16, (version >> 8) & 0xff, version & 0xff);
618#endif
619
Iliyan Malchev34193b32009-08-06 14:50:08 -0700620 device_t* device = new device_t(devid|mDevicesById[devid].seq, deviceName, name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800621 if (device == NULL) {
622 LOGE("out of memory");
623 return -1;
624 }
625
626 mFDs[mFDCount].fd = fd;
627 mFDs[mFDCount].events = POLLIN;
628
629 // figure out the kinds of events the device reports
Dianne Hackbornc5917362009-08-04 05:49:43 -0700630
Dianne Hackborn71c3eb22010-03-02 17:19:29 -0800631 // See if this is a keyboard, and classify it. Note that we only
632 // consider up through the function keys; we don't want to include
633 // ones after that (play cd etc) so we don't mistakenly consider a
634 // controller to be a keyboard.
Christopher Tate9855a052010-03-04 16:26:06 -0800635 uint8_t key_bitmask[(KEY_MAX+7)/8];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800636 memset(key_bitmask, 0, sizeof(key_bitmask));
637 LOGV("Getting keys...");
638 if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
639 //LOGI("MAP\n");
Christopher Tate9855a052010-03-04 16:26:06 -0800640 //for (int i=0; i<((KEY_MAX+7)/8); i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800641 // LOGI("%d: 0x%02x\n", i, key_bitmask[i]);
642 //}
643 for (int i=0; i<((BTN_MISC+7)/8); i++) {
644 if (key_bitmask[i] != 0) {
Jeff Browne839a582010-04-22 18:58:52 -0700645 device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800646 break;
647 }
648 }
Jeff Browne839a582010-04-22 18:58:52 -0700649 if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
Dianne Hackbornc5917362009-08-04 05:49:43 -0700650 device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800651 if (device->keyBitmask != NULL) {
652 memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
653 } else {
654 delete device;
655 LOGE("out of memory allocating key bitmask");
656 return -1;
657 }
658 }
659 }
Dianne Hackbornc5917362009-08-04 05:49:43 -0700660
661 // See if this is a trackball.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800662 if (test_bit(BTN_MOUSE, key_bitmask)) {
Christopher Tate9855a052010-03-04 16:26:06 -0800663 uint8_t rel_bitmask[(REL_MAX+7)/8];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800664 memset(rel_bitmask, 0, sizeof(rel_bitmask));
665 LOGV("Getting relative controllers...");
666 if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0)
667 {
668 if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
Jeff Browne839a582010-04-22 18:58:52 -0700669 device->classes |= INPUT_DEVICE_CLASS_TRACKBALL;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800670 }
671 }
672 }
Dianne Hackbornc5917362009-08-04 05:49:43 -0700673
Christopher Tate9855a052010-03-04 16:26:06 -0800674 uint8_t abs_bitmask[(ABS_MAX+7)/8];
Dianne Hackbornc5917362009-08-04 05:49:43 -0700675 memset(abs_bitmask, 0, sizeof(abs_bitmask));
676 LOGV("Getting absolute controllers...");
677 ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask);
678
679 // Is this a new modern multi-touch driver?
680 if (test_bit(ABS_MT_TOUCH_MAJOR, abs_bitmask)
681 && test_bit(ABS_MT_POSITION_X, abs_bitmask)
682 && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
Jeff Browne839a582010-04-22 18:58:52 -0700683 device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT;
Dianne Hackbornc5917362009-08-04 05:49:43 -0700684
685 // Is this an old style single-touch driver?
686 } else if (test_bit(BTN_TOUCH, key_bitmask)
687 && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
Jeff Browne839a582010-04-22 18:58:52 -0700688 device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800689 }
690
691#ifdef EV_SW
692 // figure out the switches this device reports
Christopher Tate9855a052010-03-04 16:26:06 -0800693 uint8_t sw_bitmask[(SW_MAX+7)/8];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800694 memset(sw_bitmask, 0, sizeof(sw_bitmask));
695 if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
696 for (int i=0; i<EV_SW; i++) {
697 //LOGI("Device 0x%x sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
698 if (test_bit(i, sw_bitmask)) {
699 if (mSwitches[i] == 0) {
700 mSwitches[i] = device->id;
701 }
702 }
703 }
704 }
705#endif
706
Jeff Browne839a582010-04-22 18:58:52 -0700707 if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
Iliyan Malchev34193b32009-08-06 14:50:08 -0700708 char tmpfn[sizeof(name)];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800709 char keylayoutFilename[300];
710
711 // a more descriptive name
Iliyan Malchev34193b32009-08-06 14:50:08 -0700712 device->name = name;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800713
714 // replace all the spaces with underscores
Iliyan Malchev34193b32009-08-06 14:50:08 -0700715 strcpy(tmpfn, name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800716 for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' '))
717 *p = '_';
718
719 // find the .kl file we need for this device
720 const char* root = getenv("ANDROID_ROOT");
721 snprintf(keylayoutFilename, sizeof(keylayoutFilename),
722 "%s/usr/keylayout/%s.kl", root, tmpfn);
723 bool defaultKeymap = false;
724 if (access(keylayoutFilename, R_OK)) {
725 snprintf(keylayoutFilename, sizeof(keylayoutFilename),
726 "%s/usr/keylayout/%s", root, "qwerty.kl");
727 defaultKeymap = true;
728 }
729 device->layoutMap->load(keylayoutFilename);
730
731 // tell the world about the devname (the descriptive name)
Dianne Hackborn71c3eb22010-03-02 17:19:29 -0800732 if (!mHaveFirstKeyboard && !defaultKeymap && strstr(name, "-keypad")) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800733 // the built-in keyboard has a well-known device ID of 0,
734 // this device better not go away.
735 mHaveFirstKeyboard = true;
736 mFirstKeyboardId = device->id;
Dianne Hackborn71c3eb22010-03-02 17:19:29 -0800737 property_set("hw.keyboards.0.devname", name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800738 } else {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800739 // ensure mFirstKeyboardId is set to -something-.
740 if (mFirstKeyboardId == 0) {
741 mFirstKeyboardId = device->id;
742 }
743 }
744 char propName[100];
Dianne Hackborn71c3eb22010-03-02 17:19:29 -0800745 sprintf(propName, "hw.keyboards.%u.devname", device->id);
Iliyan Malchev34193b32009-08-06 14:50:08 -0700746 property_set(propName, name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800747
Dianne Hackbornc5917362009-08-04 05:49:43 -0700748 // 'Q' key support = cheap test of whether this is an alpha-capable kbd
749 if (hasKeycode(device, kKeyCodeQ)) {
Jeff Browne839a582010-04-22 18:58:52 -0700750 device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
Dianne Hackbornc5917362009-08-04 05:49:43 -0700751 }
752
753 // See if this has a DPAD.
754 if (hasKeycode(device, kKeyCodeDpadUp) &&
755 hasKeycode(device, kKeyCodeDpadDown) &&
756 hasKeycode(device, kKeyCodeDpadLeft) &&
757 hasKeycode(device, kKeyCodeDpadRight) &&
758 hasKeycode(device, kKeyCodeDpadCenter)) {
Jeff Browne839a582010-04-22 18:58:52 -0700759 device->classes |= INPUT_DEVICE_CLASS_DPAD;
Dianne Hackbornc5917362009-08-04 05:49:43 -0700760 }
761
Dianne Hackborn71c3eb22010-03-02 17:19:29 -0800762 LOGI("New keyboard: device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
763 device->id, name, propName, keylayoutFilename);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800764 }
765
Dianne Hackbornc5917362009-08-04 05:49:43 -0700766 LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
767 deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes);
768
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800769 LOGV("Adding device %s %p at %d, id = %d, classes = 0x%x\n",
770 deviceName, device, mFDCount, devid, device->classes);
771
772 mDevicesById[devid].device = device;
773 device->next = mOpeningDevices;
774 mOpeningDevices = device;
775 mDevices[mFDCount] = device;
776
777 mFDCount++;
778 return 0;
779}
780
Dianne Hackbornc5917362009-08-04 05:49:43 -0700781bool EventHub::hasKeycode(device_t* device, int keycode) const
782{
783 if (device->keyBitmask == NULL || device->layoutMap == NULL) {
784 return false;
785 }
786
787 Vector<int32_t> scanCodes;
788 device->layoutMap->findScancodes(keycode, &scanCodes);
789 const size_t N = scanCodes.size();
790 for (size_t i=0; i<N && i<=KEY_MAX; i++) {
791 int32_t sc = scanCodes.itemAt(i);
792 if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) {
793 return true;
794 }
795 }
796
797 return false;
798}
799
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800800int EventHub::close_device(const char *deviceName)
801{
802 AutoMutex _l(mLock);
803
804 int i;
805 for(i = 1; i < mFDCount; i++) {
806 if(strcmp(mDevices[i]->path.string(), deviceName) == 0) {
807 //LOGD("remove device %d: %s\n", i, deviceName);
808 device_t* device = mDevices[i];
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700809
810 LOGI("Removed device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
811 device->path.string(), device->name.string(), device->id,
812 mNumDevicesById, mFDCount, mFDs[i].fd, device->classes);
813
814 // Clear this device's entry.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800815 int index = (device->id&ID_MASK);
816 mDevicesById[index].device = NULL;
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700817
818 // Close the file descriptor and compact the fd array.
Mike Lockwood07549f92009-08-28 13:29:06 -0700819 close(mFDs[i].fd);
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700820 int count = mFDCount - i - 1;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800821 memmove(mDevices + i, mDevices + i + 1, sizeof(mDevices[0]) * count);
822 memmove(mFDs + i, mFDs + i + 1, sizeof(mFDs[0]) * count);
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700823 mFDCount--;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800824
825#ifdef EV_SW
826 for (int j=0; j<EV_SW; j++) {
827 if (mSwitches[j] == device->id) {
828 mSwitches[j] = 0;
829 }
830 }
831#endif
832
833 device->next = mClosingDevices;
834 mClosingDevices = device;
835
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800836 if (device->id == mFirstKeyboardId) {
837 LOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
838 device->path.string(), mFirstKeyboardId);
839 mFirstKeyboardId = 0;
Dianne Hackborn71c3eb22010-03-02 17:19:29 -0800840 property_set("hw.keyboards.0.devname", NULL);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800841 }
842 // clear the property
843 char propName[100];
Dianne Hackborn71c3eb22010-03-02 17:19:29 -0800844 sprintf(propName, "hw.keyboards.%u.devname", device->id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800845 property_set(propName, NULL);
846 return 0;
847 }
848 }
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700849 LOGE("remove device: %s not found\n", deviceName);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800850 return -1;
851}
852
853int EventHub::read_notify(int nfd)
854{
855#ifdef HAVE_INOTIFY
856 int res;
857 char devname[PATH_MAX];
858 char *filename;
859 char event_buf[512];
860 int event_size;
861 int event_pos = 0;
862 struct inotify_event *event;
863
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700864 LOGV("EventHub::read_notify nfd: %d\n", nfd);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800865 res = read(nfd, event_buf, sizeof(event_buf));
866 if(res < (int)sizeof(*event)) {
867 if(errno == EINTR)
868 return 0;
869 LOGW("could not get event, %s\n", strerror(errno));
870 return 1;
871 }
872 //printf("got %d bytes of event information\n", res);
873
874 strcpy(devname, device_path);
875 filename = devname + strlen(devname);
876 *filename++ = '/';
877
878 while(res >= (int)sizeof(*event)) {
879 event = (struct inotify_event *)(event_buf + event_pos);
880 //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");
881 if(event->len) {
882 strcpy(filename, event->name);
883 if(event->mask & IN_CREATE) {
884 open_device(devname);
885 }
886 else {
887 close_device(devname);
888 }
889 }
890 event_size = sizeof(*event) + event->len;
891 res -= event_size;
892 event_pos += event_size;
893 }
894#endif
895 return 0;
896}
897
898
899int EventHub::scan_dir(const char *dirname)
900{
901 char devname[PATH_MAX];
902 char *filename;
903 DIR *dir;
904 struct dirent *de;
905 dir = opendir(dirname);
906 if(dir == NULL)
907 return -1;
908 strcpy(devname, dirname);
909 filename = devname + strlen(devname);
910 *filename++ = '/';
911 while((de = readdir(dir))) {
912 if(de->d_name[0] == '.' &&
913 (de->d_name[1] == '\0' ||
914 (de->d_name[1] == '.' && de->d_name[2] == '\0')))
915 continue;
916 strcpy(filename, de->d_name);
917 open_device(devname);
918 }
919 closedir(dir);
920 return 0;
921}
922
923}; // namespace android