blob: 13c30a795cb2fdd20fd15b568cc24fcabc821fe8 [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>
25#include <utils/List.h>
26#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
62namespace android {
63
64static const char *WAKE_LOCK_ID = "KeyEvents";
65static const char *device_path = "/dev/input";
66
67/* return the larger integer */
68static inline int max(int v1, int v2)
69{
70 return (v1 > v2) ? v1 : v2;
71}
72
73EventHub::device_t::device_t(int32_t _id, const char* _path)
74 : id(_id), path(_path), classes(0)
75 , keyBitmask(NULL), layoutMap(new KeyLayoutMap()), next(NULL) {
76}
77
78EventHub::device_t::~device_t() {
79 delete [] keyBitmask;
80 delete layoutMap;
81}
82
83EventHub::EventHub(void)
84 : mError(NO_INIT), mHaveFirstKeyboard(false), mFirstKeyboardId(0)
85 , mDevicesById(0), mNumDevicesById(0)
86 , mOpeningDevices(0), mClosingDevices(0)
87 , mDevices(0), mFDs(0), mFDCount(0)
88{
89 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
90#ifdef EV_SW
91 memset(mSwitches, 0, sizeof(mSwitches));
92#endif
93}
94
95/*
96 * Clean up.
97 */
98EventHub::~EventHub(void)
99{
100 release_wake_lock(WAKE_LOCK_ID);
101 // we should free stuff here...
102}
103
104void EventHub::onFirstRef()
105{
106 mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;
107}
108
109status_t EventHub::errorCheck() const
110{
111 return mError;
112}
113
114String8 EventHub::getDeviceName(int32_t deviceId) const
115{
116 AutoMutex _l(mLock);
117 device_t* device = getDevice(deviceId);
118 if (device == NULL) return String8();
119 return device->name;
120}
121
122uint32_t EventHub::getDeviceClasses(int32_t deviceId) const
123{
124 AutoMutex _l(mLock);
125 device_t* device = getDevice(deviceId);
126 if (device == NULL) return 0;
127 return device->classes;
128}
129
130int EventHub::getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue,
131 int* outMaxValue, int* outFlat, int* outFuzz) const
132{
133 AutoMutex _l(mLock);
134 device_t* device = getDevice(deviceId);
135 if (device == NULL) return -1;
136
137 struct input_absinfo info;
138
139 if(ioctl(mFDs[id_to_index(device->id)].fd, EVIOCGABS(axis), &info)) {
140 LOGE("Error reading absolute controller %d for device %s fd %d\n",
141 axis, device->name.string(), mFDs[id_to_index(device->id)].fd);
142 return -1;
143 }
144 *outMinValue = info.minimum;
145 *outMaxValue = info.maximum;
146 *outFlat = info.flat;
147 *outFuzz = info.fuzz;
148 return 0;
149}
150
151int EventHub::getSwitchState(int sw) const
152{
153#ifdef EV_SW
154 if (sw >= 0 && sw <= SW_MAX) {
155 int32_t devid = mSwitches[sw];
156 if (devid != 0) {
157 return getSwitchState(devid, sw);
158 }
159 }
160#endif
161 return -1;
162}
163
164int EventHub::getSwitchState(int32_t deviceId, int sw) const
165{
166#ifdef EV_SW
167 AutoMutex _l(mLock);
168 device_t* device = getDevice(deviceId);
169 if (device == NULL) return -1;
170
171 if (sw >= 0 && sw <= SW_MAX) {
172 uint8_t sw_bitmask[(SW_MAX+1)/8];
173 memset(sw_bitmask, 0, sizeof(sw_bitmask));
174 if (ioctl(mFDs[id_to_index(device->id)].fd,
175 EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) {
176 return test_bit(sw, sw_bitmask) ? 1 : 0;
177 }
178 }
179#endif
180
181 return -1;
182}
183
184int EventHub::getScancodeState(int code) const
185{
186 return getScancodeState(mFirstKeyboardId, code);
187}
188
189int EventHub::getScancodeState(int32_t deviceId, int code) const
190{
191 AutoMutex _l(mLock);
192 device_t* device = getDevice(deviceId);
193 if (device == NULL) return -1;
194
195 if (code >= 0 && code <= KEY_MAX) {
196 uint8_t key_bitmask[(KEY_MAX+1)/8];
197 memset(key_bitmask, 0, sizeof(key_bitmask));
198 if (ioctl(mFDs[id_to_index(device->id)].fd,
199 EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
200 return test_bit(code, key_bitmask) ? 1 : 0;
201 }
202 }
203
204 return -1;
205}
206
207int EventHub::getKeycodeState(int code) const
208{
209 return getKeycodeState(mFirstKeyboardId, code);
210}
211
212int EventHub::getKeycodeState(int32_t deviceId, int code) const
213{
214 AutoMutex _l(mLock);
215 device_t* device = getDevice(deviceId);
216 if (device == NULL || device->layoutMap == NULL) return -1;
217
218 Vector<int32_t> scanCodes;
219 device->layoutMap->findScancodes(code, &scanCodes);
220
221 uint8_t key_bitmask[(KEY_MAX+1)/8];
222 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)) {
235 return 1;
236 }
237 }
238 }
239
240 return 0;
241}
242
243EventHub::device_t* EventHub::getDevice(int32_t deviceId) const
244{
245 if (deviceId == 0) deviceId = mFirstKeyboardId;
246 int32_t id = deviceId & ID_MASK;
247 if (id >= mNumDevicesById || id < 0) return NULL;
248 device_t* dev = mDevicesById[id].device;
Dianne Hackbornc3aa00b2009-03-25 16:21:55 -0700249 if (dev == NULL) return NULL;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800250 if (dev->id == deviceId) {
251 return dev;
252 }
253 return NULL;
254}
255
256bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType,
257 int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags,
258 int32_t* outValue, nsecs_t* outWhen)
259{
260 *outDeviceId = 0;
261 *outType = 0;
262 *outScancode = 0;
263 *outKeycode = 0;
264 *outFlags = 0;
265 *outValue = 0;
266 *outWhen = 0;
267
268 status_t err;
269
270 fd_set readfds;
271 int maxFd = -1;
272 int cc;
273 int i;
274 int res;
275 int pollres;
276 struct input_event iev;
277
278 // Note that we only allow one caller to getEvent(), so don't need
279 // to do locking here... only when adding/removing devices.
280
281 while(1) {
282
283 // First, report any devices that had last been added/removed.
284 if (mClosingDevices != NULL) {
285 device_t* device = mClosingDevices;
286 LOGV("Reporting device closed: id=0x%x, name=%s\n",
287 device->id, device->path.string());
288 mClosingDevices = device->next;
289 *outDeviceId = device->id;
290 if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0;
291 *outType = DEVICE_REMOVED;
292 delete device;
293 return true;
294 }
295 if (mOpeningDevices != NULL) {
296 device_t* device = mOpeningDevices;
297 LOGV("Reporting device opened: id=0x%x, name=%s\n",
298 device->id, device->path.string());
299 mOpeningDevices = device->next;
300 *outDeviceId = device->id;
301 if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0;
302 *outType = DEVICE_ADDED;
303 return true;
304 }
305
306 release_wake_lock(WAKE_LOCK_ID);
307
308 pollres = poll(mFDs, mFDCount, -1);
309
310 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
311
312 if (pollres <= 0) {
313 if (errno != EINTR) {
314 LOGW("select failed (errno=%d)\n", errno);
315 usleep(100000);
316 }
317 continue;
318 }
319
320 //printf("poll %d, returned %d\n", mFDCount, pollres);
321
322 // mFDs[0] is used for inotify, so process regular events starting at mFDs[1]
323 for(i = 1; i < mFDCount; i++) {
324 if(mFDs[i].revents) {
325 LOGV("revents for %d = 0x%08x", i, mFDs[i].revents);
326 if(mFDs[i].revents & POLLIN) {
327 res = read(mFDs[i].fd, &iev, sizeof(iev));
328 if (res == sizeof(iev)) {
329 LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, v=%d",
330 mDevices[i]->path.string(),
331 (int) iev.time.tv_sec, (int) iev.time.tv_usec,
332 iev.type, iev.code, iev.value);
333 *outDeviceId = mDevices[i]->id;
334 if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0;
335 *outType = iev.type;
336 *outScancode = iev.code;
337 if (iev.type == EV_KEY) {
338 err = mDevices[i]->layoutMap->map(iev.code, outKeycode, outFlags);
339 LOGV("iev.code=%d outKeycode=%d outFlags=0x%08x err=%d\n",
340 iev.code, *outKeycode, *outFlags, err);
341 if (err != 0) {
342 *outKeycode = 0;
343 *outFlags = 0;
344 }
345 } else {
346 *outKeycode = iev.code;
347 }
348 *outValue = iev.value;
349 *outWhen = s2ns(iev.time.tv_sec) + us2ns(iev.time.tv_usec);
350 return true;
351 } else {
352 if (res<0) {
353 LOGW("could not get event (errno=%d)", errno);
354 } else {
355 LOGE("could not get event (wrong size: %d)", res);
356 }
357 continue;
358 }
359 }
360 }
361 }
362
363 // read_notify() will modify mFDs and mFDCount, so this must be done after
364 // processing all other events.
365 if(mFDs[0].revents & POLLIN) {
366 read_notify(mFDs[0].fd);
367 }
368 }
369}
370
371/*
372 * Open the platform-specific input device.
373 */
374bool EventHub::openPlatformInput(void)
375{
376 /*
377 * Open platform-specific input device(s).
378 */
379 int res;
380
381 mFDCount = 1;
382 mFDs = (pollfd *)calloc(1, sizeof(mFDs[0]));
383 mDevices = (device_t **)calloc(1, sizeof(mDevices[0]));
384 mFDs[0].events = POLLIN;
385 mDevices[0] = NULL;
386#ifdef HAVE_INOTIFY
387 mFDs[0].fd = inotify_init();
388 res = inotify_add_watch(mFDs[0].fd, device_path, IN_DELETE | IN_CREATE);
389 if(res < 0) {
390 LOGE("could not add watch for %s, %s\n", device_path, strerror(errno));
391 }
392#else
393 /*
394 * The code in EventHub::getEvent assumes that mFDs[0] is an inotify fd.
395 * We allocate space for it and set it to something invalid.
396 */
397 mFDs[0].fd = -1;
398#endif
399
400 res = scan_dir(device_path);
401 if(res < 0) {
402 LOGE("scan dir failed for %s\n", device_path);
403 //open_device("/dev/input/event0");
404 }
405
406 return true;
407}
408
409/*
410 * Inspect the known devices to determine whether physical keys exist for the given
411 * framework-domain key codes.
412 */
413bool EventHub::hasKeys(size_t numCodes, int32_t* keyCodes, uint8_t* outFlags) {
414 for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
415 outFlags[codeIndex] = 0;
416
417 // check each available hardware device for support for this keycode
418 Vector<int32_t> scanCodes;
419 for (int n = 0; (n < mFDCount) && (outFlags[codeIndex] == 0); n++) {
420 if (mDevices[n]) {
421 status_t err = mDevices[n]->layoutMap->findScancodes(keyCodes[codeIndex], &scanCodes);
422 if (!err) {
423 // check the possible scan codes identified by the layout map against the
424 // map of codes actually emitted by the driver
425 for (size_t sc = 0; sc < scanCodes.size(); sc++) {
426 if (test_bit(scanCodes[sc], mDevices[n]->keyBitmask)) {
427 outFlags[codeIndex] = 1;
428 break;
429 }
430 }
431 }
432 }
433 }
434 }
435
436 return true;
437}
438
439// ----------------------------------------------------------------------------
440
441int EventHub::open_device(const char *deviceName)
442{
443 int version;
444 int fd;
445 struct pollfd *new_mFDs;
446 device_t **new_devices;
447 char **new_device_names;
448 char name[80];
449 char location[80];
450 char idstr[80];
451 struct input_id id;
452
453 LOGV("Opening device: %s", deviceName);
454
455 AutoMutex _l(mLock);
456
457 fd = open(deviceName, O_RDWR);
458 if(fd < 0) {
459 LOGE("could not open %s, %s\n", deviceName, strerror(errno));
460 return -1;
461 }
462
463 if(ioctl(fd, EVIOCGVERSION, &version)) {
464 LOGE("could not get driver version for %s, %s\n", deviceName, strerror(errno));
465 return -1;
466 }
467 if(ioctl(fd, EVIOCGID, &id)) {
468 LOGE("could not get driver id for %s, %s\n", deviceName, strerror(errno));
469 return -1;
470 }
471 name[sizeof(name) - 1] = '\0';
472 location[sizeof(location) - 1] = '\0';
473 idstr[sizeof(idstr) - 1] = '\0';
474 if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
475 //fprintf(stderr, "could not get device name for %s, %s\n", deviceName, strerror(errno));
476 name[0] = '\0';
477 }
478 if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) {
479 //fprintf(stderr, "could not get location for %s, %s\n", deviceName, strerror(errno));
480 location[0] = '\0';
481 }
482 if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) {
483 //fprintf(stderr, "could not get idstring for %s, %s\n", deviceName, strerror(errno));
484 idstr[0] = '\0';
485 }
486
487 int devid = 0;
488 while (devid < mNumDevicesById) {
489 if (mDevicesById[devid].device == NULL) {
490 break;
491 }
492 devid++;
493 }
494 if (devid >= mNumDevicesById) {
495 device_ent* new_devids = (device_ent*)realloc(mDevicesById,
496 sizeof(mDevicesById[0]) * (devid + 1));
497 if (new_devids == NULL) {
498 LOGE("out of memory");
499 return -1;
500 }
501 mDevicesById = new_devids;
502 mNumDevicesById = devid+1;
503 mDevicesById[devid].device = NULL;
504 mDevicesById[devid].seq = 0;
505 }
506
507 mDevicesById[devid].seq = (mDevicesById[devid].seq+(1<<SEQ_SHIFT))&SEQ_MASK;
508 if (mDevicesById[devid].seq == 0) {
509 mDevicesById[devid].seq = 1<<SEQ_SHIFT;
510 }
511
512 new_mFDs = (pollfd*)realloc(mFDs, sizeof(mFDs[0]) * (mFDCount + 1));
513 new_devices = (device_t**)realloc(mDevices, sizeof(mDevices[0]) * (mFDCount + 1));
514 if (new_mFDs == NULL || new_devices == NULL) {
515 LOGE("out of memory");
516 return -1;
517 }
518 mFDs = new_mFDs;
519 mDevices = new_devices;
520
521#if 0
522 LOGI("add device %d: %s\n", mFDCount, deviceName);
523 LOGI(" bus: %04x\n"
524 " vendor %04x\n"
525 " product %04x\n"
526 " version %04x\n",
527 id.bustype, id.vendor, id.product, id.version);
528 LOGI(" name: \"%s\"\n", name);
529 LOGI(" location: \"%s\"\n"
530 " id: \"%s\"\n", location, idstr);
531 LOGI(" version: %d.%d.%d\n",
532 version >> 16, (version >> 8) & 0xff, version & 0xff);
533#endif
534
535 device_t* device = new device_t(devid|mDevicesById[devid].seq, deviceName);
536 if (device == NULL) {
537 LOGE("out of memory");
538 return -1;
539 }
540
541 mFDs[mFDCount].fd = fd;
542 mFDs[mFDCount].events = POLLIN;
543
544 // figure out the kinds of events the device reports
545 uint8_t key_bitmask[(KEY_MAX+1)/8];
546 memset(key_bitmask, 0, sizeof(key_bitmask));
547 LOGV("Getting keys...");
548 if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
549 //LOGI("MAP\n");
550 //for (int i=0; i<((KEY_MAX+1)/8); i++) {
551 // LOGI("%d: 0x%02x\n", i, key_bitmask[i]);
552 //}
553 for (int i=0; i<((BTN_MISC+7)/8); i++) {
554 if (key_bitmask[i] != 0) {
555 device->classes |= CLASS_KEYBOARD;
556 // 'Q' key support = cheap test of whether this is an alpha-capable kbd
557 if (test_bit(KEY_Q, key_bitmask)) {
558 device->classes |= CLASS_ALPHAKEY;
559 }
560 break;
561 }
562 }
563 if ((device->classes & CLASS_KEYBOARD) != 0) {
564 device->keyBitmask = new uint8_t[(KEY_MAX+1)/8];
565 if (device->keyBitmask != NULL) {
566 memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
567 } else {
568 delete device;
569 LOGE("out of memory allocating key bitmask");
570 return -1;
571 }
572 }
573 }
574 if (test_bit(BTN_MOUSE, key_bitmask)) {
575 uint8_t rel_bitmask[(REL_MAX+1)/8];
576 memset(rel_bitmask, 0, sizeof(rel_bitmask));
577 LOGV("Getting relative controllers...");
578 if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0)
579 {
580 if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
581 device->classes |= CLASS_TRACKBALL;
582 }
583 }
584 }
585 if (test_bit(BTN_TOUCH, key_bitmask)) {
586 uint8_t abs_bitmask[(ABS_MAX+1)/8];
587 memset(abs_bitmask, 0, sizeof(abs_bitmask));
588 LOGV("Getting absolute controllers...");
589 if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0)
590 {
591 if (test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
592 device->classes |= CLASS_TOUCHSCREEN;
593 }
594 }
595 }
596
597#ifdef EV_SW
598 // figure out the switches this device reports
599 uint8_t sw_bitmask[(SW_MAX+1)/8];
600 memset(sw_bitmask, 0, sizeof(sw_bitmask));
601 if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
602 for (int i=0; i<EV_SW; i++) {
603 //LOGI("Device 0x%x sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
604 if (test_bit(i, sw_bitmask)) {
605 if (mSwitches[i] == 0) {
606 mSwitches[i] = device->id;
607 }
608 }
609 }
610 }
611#endif
612
613 LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
614 deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes);
615
616 if ((device->classes&CLASS_KEYBOARD) != 0) {
617 char devname[101];
618 char tmpfn[101];
619 char keylayoutFilename[300];
620
621 // a more descriptive name
622 ioctl(mFDs[mFDCount].fd, EVIOCGNAME(sizeof(devname)-1), devname);
623 devname[sizeof(devname)-1] = 0;
624 device->name = devname;
625
626 // replace all the spaces with underscores
627 strcpy(tmpfn, devname);
628 for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' '))
629 *p = '_';
630
631 // find the .kl file we need for this device
632 const char* root = getenv("ANDROID_ROOT");
633 snprintf(keylayoutFilename, sizeof(keylayoutFilename),
634 "%s/usr/keylayout/%s.kl", root, tmpfn);
635 bool defaultKeymap = false;
636 if (access(keylayoutFilename, R_OK)) {
637 snprintf(keylayoutFilename, sizeof(keylayoutFilename),
638 "%s/usr/keylayout/%s", root, "qwerty.kl");
639 defaultKeymap = true;
640 }
641 device->layoutMap->load(keylayoutFilename);
642
643 // tell the world about the devname (the descriptive name)
644 int32_t publicID;
645 if (!mHaveFirstKeyboard && !defaultKeymap) {
646 publicID = 0;
647 // the built-in keyboard has a well-known device ID of 0,
648 // this device better not go away.
649 mHaveFirstKeyboard = true;
650 mFirstKeyboardId = device->id;
651 } else {
652 publicID = device->id;
653 // ensure mFirstKeyboardId is set to -something-.
654 if (mFirstKeyboardId == 0) {
655 mFirstKeyboardId = device->id;
656 }
657 }
658 char propName[100];
659 sprintf(propName, "hw.keyboards.%u.devname", publicID);
660 property_set(propName, devname);
661
662 LOGI("New keyboard: publicID=%d device->id=%d devname='%s' propName='%s' keylayout='%s'\n",
663 publicID, device->id, devname, propName, keylayoutFilename);
664 }
665
666 LOGV("Adding device %s %p at %d, id = %d, classes = 0x%x\n",
667 deviceName, device, mFDCount, devid, device->classes);
668
669 mDevicesById[devid].device = device;
670 device->next = mOpeningDevices;
671 mOpeningDevices = device;
672 mDevices[mFDCount] = device;
673
674 mFDCount++;
675 return 0;
676}
677
678int EventHub::close_device(const char *deviceName)
679{
680 AutoMutex _l(mLock);
681
682 int i;
683 for(i = 1; i < mFDCount; i++) {
684 if(strcmp(mDevices[i]->path.string(), deviceName) == 0) {
685 //LOGD("remove device %d: %s\n", i, deviceName);
686 device_t* device = mDevices[i];
687 int count = mFDCount - i - 1;
688 int index = (device->id&ID_MASK);
689 mDevicesById[index].device = NULL;
690 memmove(mDevices + i, mDevices + i + 1, sizeof(mDevices[0]) * count);
691 memmove(mFDs + i, mFDs + i + 1, sizeof(mFDs[0]) * count);
692
693#ifdef EV_SW
694 for (int j=0; j<EV_SW; j++) {
695 if (mSwitches[j] == device->id) {
696 mSwitches[j] = 0;
697 }
698 }
699#endif
700
701 device->next = mClosingDevices;
702 mClosingDevices = device;
703
704 mFDCount--;
705
706 uint32_t publicID;
707 if (device->id == mFirstKeyboardId) {
708 LOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
709 device->path.string(), mFirstKeyboardId);
710 mFirstKeyboardId = 0;
711 publicID = 0;
712 } else {
713 publicID = device->id;
714 }
715 // clear the property
716 char propName[100];
717 sprintf(propName, "hw.keyboards.%u.devname", publicID);
718 property_set(propName, NULL);
719 return 0;
720 }
721 }
722 LOGE("remote device: %s not found\n", deviceName);
723 return -1;
724}
725
726int EventHub::read_notify(int nfd)
727{
728#ifdef HAVE_INOTIFY
729 int res;
730 char devname[PATH_MAX];
731 char *filename;
732 char event_buf[512];
733 int event_size;
734 int event_pos = 0;
735 struct inotify_event *event;
736
737 res = read(nfd, event_buf, sizeof(event_buf));
738 if(res < (int)sizeof(*event)) {
739 if(errno == EINTR)
740 return 0;
741 LOGW("could not get event, %s\n", strerror(errno));
742 return 1;
743 }
744 //printf("got %d bytes of event information\n", res);
745
746 strcpy(devname, device_path);
747 filename = devname + strlen(devname);
748 *filename++ = '/';
749
750 while(res >= (int)sizeof(*event)) {
751 event = (struct inotify_event *)(event_buf + event_pos);
752 //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");
753 if(event->len) {
754 strcpy(filename, event->name);
755 if(event->mask & IN_CREATE) {
756 open_device(devname);
757 }
758 else {
759 close_device(devname);
760 }
761 }
762 event_size = sizeof(*event) + event->len;
763 res -= event_size;
764 event_pos += event_size;
765 }
766#endif
767 return 0;
768}
769
770
771int EventHub::scan_dir(const char *dirname)
772{
773 char devname[PATH_MAX];
774 char *filename;
775 DIR *dir;
776 struct dirent *de;
777 dir = opendir(dirname);
778 if(dir == NULL)
779 return -1;
780 strcpy(devname, dirname);
781 filename = devname + strlen(devname);
782 *filename++ = '/';
783 while((de = readdir(dir))) {
784 if(de->d_name[0] == '.' &&
785 (de->d_name[1] == '\0' ||
786 (de->d_name[1] == '.' && de->d_name[2] == '\0')))
787 continue;
788 strcpy(filename, de->d_name);
789 open_device(devname);
790 }
791 closedir(dir);
792 return 0;
793}
794
795}; // namespace android