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