1//
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;
248    if (dev == NULL) return NULL;
249    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
795