blob: 4aac455153dbffb29f5e98455d090c659bcae711 [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
158int EventHub::getSwitchState(int sw) const
159{
160#ifdef EV_SW
161 if (sw >= 0 && sw <= SW_MAX) {
162 int32_t devid = mSwitches[sw];
163 if (devid != 0) {
164 return getSwitchState(devid, sw);
165 }
166 }
167#endif
168 return -1;
169}
170
171int EventHub::getSwitchState(int32_t deviceId, int sw) const
172{
173#ifdef EV_SW
174 AutoMutex _l(mLock);
175 device_t* device = getDevice(deviceId);
176 if (device == NULL) return -1;
177
178 if (sw >= 0 && sw <= SW_MAX) {
179 uint8_t sw_bitmask[(SW_MAX+1)/8];
180 memset(sw_bitmask, 0, sizeof(sw_bitmask));
181 if (ioctl(mFDs[id_to_index(device->id)].fd,
182 EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) {
183 return test_bit(sw, sw_bitmask) ? 1 : 0;
184 }
185 }
186#endif
187
188 return -1;
189}
190
191int EventHub::getScancodeState(int code) const
192{
193 return getScancodeState(mFirstKeyboardId, code);
194}
195
196int EventHub::getScancodeState(int32_t deviceId, int code) const
197{
198 AutoMutex _l(mLock);
199 device_t* device = getDevice(deviceId);
200 if (device == NULL) return -1;
201
202 if (code >= 0 && code <= KEY_MAX) {
203 uint8_t key_bitmask[(KEY_MAX+1)/8];
204 memset(key_bitmask, 0, sizeof(key_bitmask));
205 if (ioctl(mFDs[id_to_index(device->id)].fd,
206 EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
207 return test_bit(code, key_bitmask) ? 1 : 0;
208 }
209 }
210
211 return -1;
212}
213
214int EventHub::getKeycodeState(int code) const
215{
216 return getKeycodeState(mFirstKeyboardId, code);
217}
218
219int EventHub::getKeycodeState(int32_t deviceId, int code) const
220{
221 AutoMutex _l(mLock);
222 device_t* device = getDevice(deviceId);
223 if (device == NULL || device->layoutMap == NULL) return -1;
224
225 Vector<int32_t> scanCodes;
226 device->layoutMap->findScancodes(code, &scanCodes);
227
228 uint8_t key_bitmask[(KEY_MAX+1)/8];
229 memset(key_bitmask, 0, sizeof(key_bitmask));
230 if (ioctl(mFDs[id_to_index(device->id)].fd,
231 EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
232 #if 0
233 for (size_t i=0; i<=KEY_MAX; i++) {
234 LOGI("(Scan code %d: down=%d)", i, test_bit(i, key_bitmask));
235 }
236 #endif
237 const size_t N = scanCodes.size();
238 for (size_t i=0; i<N && i<=KEY_MAX; i++) {
239 int32_t sc = scanCodes.itemAt(i);
240 //LOGI("Code %d: down=%d", sc, test_bit(sc, key_bitmask));
241 if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, key_bitmask)) {
242 return 1;
243 }
244 }
245 }
246
247 return 0;
248}
249
Dianne Hackbornc968c3a2009-07-14 12:06:54 -0700250status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode,
251 int32_t* outKeycode, uint32_t* outFlags) const
252{
253 AutoMutex _l(mLock);
254 device_t* device = getDevice(deviceId);
255
256 if (device != NULL && device->layoutMap != NULL) {
257 status_t err = device->layoutMap->map(scancode, outKeycode, outFlags);
258 if (err == NO_ERROR) {
259 return NO_ERROR;
260 }
261 }
262
263 if (mHaveFirstKeyboard) {
264 device = getDevice(mFirstKeyboardId);
265
266 if (device != NULL && device->layoutMap != NULL) {
267 status_t err = device->layoutMap->map(scancode, outKeycode, outFlags);
268 if (err == NO_ERROR) {
269 return NO_ERROR;
270 }
271 }
272 }
273
274 *outKeycode = 0;
275 *outFlags = 0;
276 return NAME_NOT_FOUND;
277}
278
Mike Lockwoodb4411062009-07-16 11:11:18 -0400279void EventHub::addExcludedDevice(const char* deviceName)
280{
281 String8 name(deviceName);
282 mExcludedDevices.push_back(name);
283}
284
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800285EventHub::device_t* EventHub::getDevice(int32_t deviceId) const
286{
287 if (deviceId == 0) deviceId = mFirstKeyboardId;
288 int32_t id = deviceId & ID_MASK;
289 if (id >= mNumDevicesById || id < 0) return NULL;
290 device_t* dev = mDevicesById[id].device;
Dianne Hackbornc3aa00b2009-03-25 16:21:55 -0700291 if (dev == NULL) return NULL;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800292 if (dev->id == deviceId) {
293 return dev;
294 }
295 return NULL;
296}
297
298bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType,
299 int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags,
300 int32_t* outValue, nsecs_t* outWhen)
301{
302 *outDeviceId = 0;
303 *outType = 0;
304 *outScancode = 0;
305 *outKeycode = 0;
306 *outFlags = 0;
307 *outValue = 0;
308 *outWhen = 0;
309
310 status_t err;
311
312 fd_set readfds;
313 int maxFd = -1;
314 int cc;
315 int i;
316 int res;
317 int pollres;
318 struct input_event iev;
319
320 // Note that we only allow one caller to getEvent(), so don't need
321 // to do locking here... only when adding/removing devices.
Mike Lockwoodb4411062009-07-16 11:11:18 -0400322
323 if (!mOpened) {
324 mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;
325 mOpened = true;
326 }
327
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800328 while(1) {
329
330 // First, report any devices that had last been added/removed.
331 if (mClosingDevices != NULL) {
332 device_t* device = mClosingDevices;
333 LOGV("Reporting device closed: id=0x%x, name=%s\n",
334 device->id, device->path.string());
335 mClosingDevices = device->next;
336 *outDeviceId = device->id;
337 if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0;
338 *outType = DEVICE_REMOVED;
339 delete device;
340 return true;
341 }
342 if (mOpeningDevices != NULL) {
343 device_t* device = mOpeningDevices;
344 LOGV("Reporting device opened: id=0x%x, name=%s\n",
345 device->id, device->path.string());
346 mOpeningDevices = device->next;
347 *outDeviceId = device->id;
348 if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0;
349 *outType = DEVICE_ADDED;
350 return true;
351 }
352
353 release_wake_lock(WAKE_LOCK_ID);
354
355 pollres = poll(mFDs, mFDCount, -1);
356
357 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
358
359 if (pollres <= 0) {
360 if (errno != EINTR) {
361 LOGW("select failed (errno=%d)\n", errno);
362 usleep(100000);
363 }
364 continue;
365 }
366
367 //printf("poll %d, returned %d\n", mFDCount, pollres);
368
369 // mFDs[0] is used for inotify, so process regular events starting at mFDs[1]
370 for(i = 1; i < mFDCount; i++) {
371 if(mFDs[i].revents) {
372 LOGV("revents for %d = 0x%08x", i, mFDs[i].revents);
373 if(mFDs[i].revents & POLLIN) {
374 res = read(mFDs[i].fd, &iev, sizeof(iev));
375 if (res == sizeof(iev)) {
376 LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, v=%d",
377 mDevices[i]->path.string(),
378 (int) iev.time.tv_sec, (int) iev.time.tv_usec,
379 iev.type, iev.code, iev.value);
380 *outDeviceId = mDevices[i]->id;
381 if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0;
382 *outType = iev.type;
383 *outScancode = iev.code;
384 if (iev.type == EV_KEY) {
385 err = mDevices[i]->layoutMap->map(iev.code, outKeycode, outFlags);
386 LOGV("iev.code=%d outKeycode=%d outFlags=0x%08x err=%d\n",
387 iev.code, *outKeycode, *outFlags, err);
388 if (err != 0) {
389 *outKeycode = 0;
390 *outFlags = 0;
391 }
392 } else {
393 *outKeycode = iev.code;
394 }
395 *outValue = iev.value;
396 *outWhen = s2ns(iev.time.tv_sec) + us2ns(iev.time.tv_usec);
397 return true;
398 } else {
399 if (res<0) {
400 LOGW("could not get event (errno=%d)", errno);
401 } else {
402 LOGE("could not get event (wrong size: %d)", res);
403 }
404 continue;
405 }
406 }
407 }
408 }
409
410 // read_notify() will modify mFDs and mFDCount, so this must be done after
411 // processing all other events.
412 if(mFDs[0].revents & POLLIN) {
413 read_notify(mFDs[0].fd);
414 }
415 }
416}
417
418/*
419 * Open the platform-specific input device.
420 */
421bool EventHub::openPlatformInput(void)
422{
423 /*
424 * Open platform-specific input device(s).
425 */
426 int res;
427
428 mFDCount = 1;
429 mFDs = (pollfd *)calloc(1, sizeof(mFDs[0]));
430 mDevices = (device_t **)calloc(1, sizeof(mDevices[0]));
431 mFDs[0].events = POLLIN;
432 mDevices[0] = NULL;
433#ifdef HAVE_INOTIFY
434 mFDs[0].fd = inotify_init();
435 res = inotify_add_watch(mFDs[0].fd, device_path, IN_DELETE | IN_CREATE);
436 if(res < 0) {
437 LOGE("could not add watch for %s, %s\n", device_path, strerror(errno));
438 }
439#else
440 /*
441 * The code in EventHub::getEvent assumes that mFDs[0] is an inotify fd.
442 * We allocate space for it and set it to something invalid.
443 */
444 mFDs[0].fd = -1;
445#endif
446
447 res = scan_dir(device_path);
448 if(res < 0) {
449 LOGE("scan dir failed for %s\n", device_path);
450 //open_device("/dev/input/event0");
451 }
452
453 return true;
454}
455
456/*
457 * Inspect the known devices to determine whether physical keys exist for the given
458 * framework-domain key codes.
459 */
460bool EventHub::hasKeys(size_t numCodes, int32_t* keyCodes, uint8_t* outFlags) {
461 for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
462 outFlags[codeIndex] = 0;
463
464 // check each available hardware device for support for this keycode
465 Vector<int32_t> scanCodes;
466 for (int n = 0; (n < mFDCount) && (outFlags[codeIndex] == 0); n++) {
467 if (mDevices[n]) {
468 status_t err = mDevices[n]->layoutMap->findScancodes(keyCodes[codeIndex], &scanCodes);
469 if (!err) {
470 // check the possible scan codes identified by the layout map against the
471 // map of codes actually emitted by the driver
472 for (size_t sc = 0; sc < scanCodes.size(); sc++) {
473 if (test_bit(scanCodes[sc], mDevices[n]->keyBitmask)) {
474 outFlags[codeIndex] = 1;
475 break;
476 }
477 }
478 }
479 }
480 }
481 }
482
483 return true;
484}
485
486// ----------------------------------------------------------------------------
487
488int EventHub::open_device(const char *deviceName)
489{
490 int version;
491 int fd;
Nick Pellyc81bb202010-01-20 19:36:49 -0800492 int attempt;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800493 struct pollfd *new_mFDs;
494 device_t **new_devices;
495 char **new_device_names;
496 char name[80];
497 char location[80];
498 char idstr[80];
499 struct input_id id;
500
501 LOGV("Opening device: %s", deviceName);
502
503 AutoMutex _l(mLock);
Nick Pellyc81bb202010-01-20 19:36:49 -0800504
505 for (attempt = 0; attempt < 10; attempt++) {
506 fd = open(deviceName, O_RDWR);
507 if (fd >= 0) break;
508 usleep(100);
509 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800510 if(fd < 0) {
511 LOGE("could not open %s, %s\n", deviceName, strerror(errno));
512 return -1;
513 }
Nick Pellyc81bb202010-01-20 19:36:49 -0800514 LOGV("Opened device: %s (%d failures)", deviceName, attempt);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800515
516 if(ioctl(fd, EVIOCGVERSION, &version)) {
517 LOGE("could not get driver version for %s, %s\n", deviceName, strerror(errno));
518 return -1;
519 }
520 if(ioctl(fd, EVIOCGID, &id)) {
521 LOGE("could not get driver id for %s, %s\n", deviceName, strerror(errno));
522 return -1;
523 }
524 name[sizeof(name) - 1] = '\0';
525 location[sizeof(location) - 1] = '\0';
526 idstr[sizeof(idstr) - 1] = '\0';
527 if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
528 //fprintf(stderr, "could not get device name for %s, %s\n", deviceName, strerror(errno));
529 name[0] = '\0';
530 }
Mike Lockwood24a7e042009-07-17 00:10:10 -0400531
532 // check to see if the device is on our excluded list
533 List<String8>::iterator iter = mExcludedDevices.begin();
534 List<String8>::iterator end = mExcludedDevices.end();
535 for ( ; iter != end; iter++) {
536 const char* test = *iter;
537 if (strcmp(name, test) == 0) {
538 LOGI("ignoring event id %s driver %s\n", deviceName, test);
539 close(fd);
540 fd = -1;
541 return -1;
542 }
543 }
544
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800545 if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) {
546 //fprintf(stderr, "could not get location for %s, %s\n", deviceName, strerror(errno));
547 location[0] = '\0';
548 }
549 if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) {
550 //fprintf(stderr, "could not get idstring for %s, %s\n", deviceName, strerror(errno));
551 idstr[0] = '\0';
552 }
553
554 int devid = 0;
555 while (devid < mNumDevicesById) {
556 if (mDevicesById[devid].device == NULL) {
557 break;
558 }
559 devid++;
560 }
561 if (devid >= mNumDevicesById) {
562 device_ent* new_devids = (device_ent*)realloc(mDevicesById,
563 sizeof(mDevicesById[0]) * (devid + 1));
564 if (new_devids == NULL) {
565 LOGE("out of memory");
566 return -1;
567 }
568 mDevicesById = new_devids;
569 mNumDevicesById = devid+1;
570 mDevicesById[devid].device = NULL;
571 mDevicesById[devid].seq = 0;
572 }
573
574 mDevicesById[devid].seq = (mDevicesById[devid].seq+(1<<SEQ_SHIFT))&SEQ_MASK;
575 if (mDevicesById[devid].seq == 0) {
576 mDevicesById[devid].seq = 1<<SEQ_SHIFT;
577 }
578
579 new_mFDs = (pollfd*)realloc(mFDs, sizeof(mFDs[0]) * (mFDCount + 1));
580 new_devices = (device_t**)realloc(mDevices, sizeof(mDevices[0]) * (mFDCount + 1));
581 if (new_mFDs == NULL || new_devices == NULL) {
582 LOGE("out of memory");
583 return -1;
584 }
585 mFDs = new_mFDs;
586 mDevices = new_devices;
587
588#if 0
589 LOGI("add device %d: %s\n", mFDCount, deviceName);
590 LOGI(" bus: %04x\n"
591 " vendor %04x\n"
592 " product %04x\n"
593 " version %04x\n",
594 id.bustype, id.vendor, id.product, id.version);
595 LOGI(" name: \"%s\"\n", name);
596 LOGI(" location: \"%s\"\n"
597 " id: \"%s\"\n", location, idstr);
598 LOGI(" version: %d.%d.%d\n",
599 version >> 16, (version >> 8) & 0xff, version & 0xff);
600#endif
601
Iliyan Malchev34193b32009-08-06 14:50:08 -0700602 device_t* device = new device_t(devid|mDevicesById[devid].seq, deviceName, name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800603 if (device == NULL) {
604 LOGE("out of memory");
605 return -1;
606 }
607
608 mFDs[mFDCount].fd = fd;
609 mFDs[mFDCount].events = POLLIN;
610
611 // figure out the kinds of events the device reports
Dianne Hackbornc5917362009-08-04 05:49:43 -0700612
613 // See if this is a keyboard, and classify it.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800614 uint8_t key_bitmask[(KEY_MAX+1)/8];
615 memset(key_bitmask, 0, sizeof(key_bitmask));
616 LOGV("Getting keys...");
617 if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
618 //LOGI("MAP\n");
619 //for (int i=0; i<((KEY_MAX+1)/8); i++) {
620 // LOGI("%d: 0x%02x\n", i, key_bitmask[i]);
621 //}
622 for (int i=0; i<((BTN_MISC+7)/8); i++) {
623 if (key_bitmask[i] != 0) {
624 device->classes |= CLASS_KEYBOARD;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800625 break;
626 }
627 }
628 if ((device->classes & CLASS_KEYBOARD) != 0) {
Dianne Hackbornc5917362009-08-04 05:49:43 -0700629 device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800630 if (device->keyBitmask != NULL) {
631 memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
632 } else {
633 delete device;
634 LOGE("out of memory allocating key bitmask");
635 return -1;
636 }
637 }
638 }
Dianne Hackbornc5917362009-08-04 05:49:43 -0700639
640 // See if this is a trackball.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800641 if (test_bit(BTN_MOUSE, key_bitmask)) {
642 uint8_t rel_bitmask[(REL_MAX+1)/8];
643 memset(rel_bitmask, 0, sizeof(rel_bitmask));
644 LOGV("Getting relative controllers...");
645 if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0)
646 {
647 if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
648 device->classes |= CLASS_TRACKBALL;
649 }
650 }
651 }
Dianne Hackbornc5917362009-08-04 05:49:43 -0700652
653 uint8_t abs_bitmask[(ABS_MAX+1)/8];
654 memset(abs_bitmask, 0, sizeof(abs_bitmask));
655 LOGV("Getting absolute controllers...");
656 ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask);
657
658 // Is this a new modern multi-touch driver?
659 if (test_bit(ABS_MT_TOUCH_MAJOR, abs_bitmask)
660 && test_bit(ABS_MT_POSITION_X, abs_bitmask)
661 && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
662 device->classes |= CLASS_TOUCHSCREEN | CLASS_TOUCHSCREEN_MT;
663
664 // Is this an old style single-touch driver?
665 } else if (test_bit(BTN_TOUCH, key_bitmask)
666 && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
667 device->classes |= CLASS_TOUCHSCREEN;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800668 }
669
670#ifdef EV_SW
671 // figure out the switches this device reports
672 uint8_t sw_bitmask[(SW_MAX+1)/8];
673 memset(sw_bitmask, 0, sizeof(sw_bitmask));
674 if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
675 for (int i=0; i<EV_SW; i++) {
676 //LOGI("Device 0x%x sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
677 if (test_bit(i, sw_bitmask)) {
678 if (mSwitches[i] == 0) {
679 mSwitches[i] = device->id;
680 }
681 }
682 }
683 }
684#endif
685
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800686 if ((device->classes&CLASS_KEYBOARD) != 0) {
Iliyan Malchev34193b32009-08-06 14:50:08 -0700687 char tmpfn[sizeof(name)];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800688 char keylayoutFilename[300];
689
690 // a more descriptive name
Iliyan Malchev34193b32009-08-06 14:50:08 -0700691 device->name = name;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800692
693 // replace all the spaces with underscores
Iliyan Malchev34193b32009-08-06 14:50:08 -0700694 strcpy(tmpfn, name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800695 for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' '))
696 *p = '_';
697
698 // find the .kl file we need for this device
699 const char* root = getenv("ANDROID_ROOT");
700 snprintf(keylayoutFilename, sizeof(keylayoutFilename),
701 "%s/usr/keylayout/%s.kl", root, tmpfn);
702 bool defaultKeymap = false;
703 if (access(keylayoutFilename, R_OK)) {
704 snprintf(keylayoutFilename, sizeof(keylayoutFilename),
705 "%s/usr/keylayout/%s", root, "qwerty.kl");
706 defaultKeymap = true;
707 }
708 device->layoutMap->load(keylayoutFilename);
709
710 // tell the world about the devname (the descriptive name)
711 int32_t publicID;
712 if (!mHaveFirstKeyboard && !defaultKeymap) {
713 publicID = 0;
714 // the built-in keyboard has a well-known device ID of 0,
715 // this device better not go away.
716 mHaveFirstKeyboard = true;
717 mFirstKeyboardId = device->id;
718 } else {
719 publicID = device->id;
720 // ensure mFirstKeyboardId is set to -something-.
721 if (mFirstKeyboardId == 0) {
722 mFirstKeyboardId = device->id;
723 }
724 }
725 char propName[100];
726 sprintf(propName, "hw.keyboards.%u.devname", publicID);
Iliyan Malchev34193b32009-08-06 14:50:08 -0700727 property_set(propName, name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800728
Dianne Hackbornc5917362009-08-04 05:49:43 -0700729 // 'Q' key support = cheap test of whether this is an alpha-capable kbd
730 if (hasKeycode(device, kKeyCodeQ)) {
731 device->classes |= CLASS_ALPHAKEY;
732 }
733
734 // See if this has a DPAD.
735 if (hasKeycode(device, kKeyCodeDpadUp) &&
736 hasKeycode(device, kKeyCodeDpadDown) &&
737 hasKeycode(device, kKeyCodeDpadLeft) &&
738 hasKeycode(device, kKeyCodeDpadRight) &&
739 hasKeycode(device, kKeyCodeDpadCenter)) {
740 device->classes |= CLASS_DPAD;
741 }
742
743 LOGI("New keyboard: publicID=%d device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
Iliyan Malchev34193b32009-08-06 14:50:08 -0700744 publicID, device->id, name, propName, keylayoutFilename);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800745 }
746
Dianne Hackbornc5917362009-08-04 05:49:43 -0700747 LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
748 deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes);
749
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800750 LOGV("Adding device %s %p at %d, id = %d, classes = 0x%x\n",
751 deviceName, device, mFDCount, devid, device->classes);
752
753 mDevicesById[devid].device = device;
754 device->next = mOpeningDevices;
755 mOpeningDevices = device;
756 mDevices[mFDCount] = device;
757
758 mFDCount++;
759 return 0;
760}
761
Dianne Hackbornc5917362009-08-04 05:49:43 -0700762bool EventHub::hasKeycode(device_t* device, int keycode) const
763{
764 if (device->keyBitmask == NULL || device->layoutMap == NULL) {
765 return false;
766 }
767
768 Vector<int32_t> scanCodes;
769 device->layoutMap->findScancodes(keycode, &scanCodes);
770 const size_t N = scanCodes.size();
771 for (size_t i=0; i<N && i<=KEY_MAX; i++) {
772 int32_t sc = scanCodes.itemAt(i);
773 if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) {
774 return true;
775 }
776 }
777
778 return false;
779}
780
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800781int EventHub::close_device(const char *deviceName)
782{
783 AutoMutex _l(mLock);
784
785 int i;
786 for(i = 1; i < mFDCount; i++) {
787 if(strcmp(mDevices[i]->path.string(), deviceName) == 0) {
788 //LOGD("remove device %d: %s\n", i, deviceName);
789 device_t* device = mDevices[i];
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700790
791 LOGI("Removed device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
792 device->path.string(), device->name.string(), device->id,
793 mNumDevicesById, mFDCount, mFDs[i].fd, device->classes);
794
795 // Clear this device's entry.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800796 int index = (device->id&ID_MASK);
797 mDevicesById[index].device = NULL;
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700798
799 // Close the file descriptor and compact the fd array.
Mike Lockwood07549f92009-08-28 13:29:06 -0700800 close(mFDs[i].fd);
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700801 int count = mFDCount - i - 1;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800802 memmove(mDevices + i, mDevices + i + 1, sizeof(mDevices[0]) * count);
803 memmove(mFDs + i, mFDs + i + 1, sizeof(mFDs[0]) * count);
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700804 mFDCount--;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800805
806#ifdef EV_SW
807 for (int j=0; j<EV_SW; j++) {
808 if (mSwitches[j] == device->id) {
809 mSwitches[j] = 0;
810 }
811 }
812#endif
813
814 device->next = mClosingDevices;
815 mClosingDevices = device;
816
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800817 uint32_t publicID;
818 if (device->id == mFirstKeyboardId) {
819 LOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
820 device->path.string(), mFirstKeyboardId);
821 mFirstKeyboardId = 0;
822 publicID = 0;
823 } else {
824 publicID = device->id;
825 }
826 // clear the property
827 char propName[100];
828 sprintf(propName, "hw.keyboards.%u.devname", publicID);
829 property_set(propName, NULL);
830 return 0;
831 }
832 }
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700833 LOGE("remove device: %s not found\n", deviceName);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800834 return -1;
835}
836
837int EventHub::read_notify(int nfd)
838{
839#ifdef HAVE_INOTIFY
840 int res;
841 char devname[PATH_MAX];
842 char *filename;
843 char event_buf[512];
844 int event_size;
845 int event_pos = 0;
846 struct inotify_event *event;
847
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700848 LOGV("EventHub::read_notify nfd: %d\n", nfd);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800849 res = read(nfd, event_buf, sizeof(event_buf));
850 if(res < (int)sizeof(*event)) {
851 if(errno == EINTR)
852 return 0;
853 LOGW("could not get event, %s\n", strerror(errno));
854 return 1;
855 }
856 //printf("got %d bytes of event information\n", res);
857
858 strcpy(devname, device_path);
859 filename = devname + strlen(devname);
860 *filename++ = '/';
861
862 while(res >= (int)sizeof(*event)) {
863 event = (struct inotify_event *)(event_buf + event_pos);
864 //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");
865 if(event->len) {
866 strcpy(filename, event->name);
867 if(event->mask & IN_CREATE) {
868 open_device(devname);
869 }
870 else {
871 close_device(devname);
872 }
873 }
874 event_size = sizeof(*event) + event->len;
875 res -= event_size;
876 event_pos += event_size;
877 }
878#endif
879 return 0;
880}
881
882
883int EventHub::scan_dir(const char *dirname)
884{
885 char devname[PATH_MAX];
886 char *filename;
887 DIR *dir;
888 struct dirent *de;
889 dir = opendir(dirname);
890 if(dir == NULL)
891 return -1;
892 strcpy(devname, dirname);
893 filename = devname + strlen(devname);
894 *filename++ = '/';
895 while((de = readdir(dir))) {
896 if(de->d_name[0] == '.' &&
897 (de->d_name[1] == '\0' ||
898 (de->d_name[1] == '.' && de->d_name[2] == '\0')))
899 continue;
900 strcpy(filename, de->d_name);
901 open_device(devname);
902 }
903 closedir(dir);
904 return 0;
905}
906
907}; // namespace android