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