blob: 891661d690ac552097aff91925eaa456247ad7f4 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001//
2// Copyright 2005 The Android Open Source Project
3//
4// Handle events, like key input and vsync.
5//
6// The goal is to provide an optimized solution for Linux, not an
7// implementation that works well across all platforms. We expect
8// events to arrive on file descriptors, so that we can use a select()
9// select() call to sleep.
10//
11// We can't select() on anything but network sockets in Windows, so we
12// provide an alternative implementation of waitEvent for that platform.
13//
14#define LOG_TAG "EventHub"
15
16//#define LOG_NDEBUG 0
17
18#include <ui/EventHub.h>
Dianne Hackbornc5917362009-08-04 05:49:43 -070019#include <ui/KeycodeLabels.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080020#include <hardware_legacy/power.h>
21
22#include <cutils/properties.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080023#include <utils/Log.h>
24#include <utils/Timers.h>
Mathias Agopiane0c32202009-05-31 19:13:00 -070025#include <utils/threads.h>
Mathias Agopiane0c32202009-05-31 19:13:00 -070026#include <utils/Errors.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080027
28#include <stdlib.h>
29#include <stdio.h>
30#include <unistd.h>
31#include <fcntl.h>
32#include <memory.h>
33#include <errno.h>
34#include <assert.h>
35
36#include "KeyLayoutMap.h"
37
38#include <string.h>
39#include <stdint.h>
40#include <dirent.h>
41#ifdef HAVE_INOTIFY
42# include <sys/inotify.h>
43#endif
44#ifdef HAVE_ANDROID_OS
45# include <sys/limits.h> /* not part of Linux */
46#endif
47#include <sys/poll.h>
48#include <sys/ioctl.h>
49
50/* this macro is used to tell if "bit" is set in "array"
51 * it selects a byte from the array, and does a boolean AND
52 * operation with a byte that only has the relevant bit set.
53 * eg. to check for the 12th bit, we do (array[1] & 1<<4)
54 */
55#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8)))
56
Jeff Brown8575a872010-06-30 16:10:35 -070057/* this macro computes the number of bytes needed to represent a bit array of the specified size */
58#define sizeof_bit_array(bits) ((bits + 7) / 8)
59
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080060#define ID_MASK 0x0000ffff
61#define SEQ_MASK 0x7fff0000
62#define SEQ_SHIFT 16
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080063
Dianne Hackbornc5917362009-08-04 05:49:43 -070064#ifndef ABS_MT_TOUCH_MAJOR
65#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
66#endif
67
68#ifndef ABS_MT_POSITION_X
69#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
70#endif
71
72#ifndef ABS_MT_POSITION_Y
73#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
74#endif
75
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080076namespace android {
77
78static const char *WAKE_LOCK_ID = "KeyEvents";
79static const char *device_path = "/dev/input";
80
81/* return the larger integer */
82static inline int max(int v1, int v2)
83{
84 return (v1 > v2) ? v1 : v2;
85}
86
Iliyan Malchev34193b32009-08-06 14:50:08 -070087EventHub::device_t::device_t(int32_t _id, const char* _path, const char* name)
88 : id(_id), path(_path), name(name), classes(0)
Jens Gulin7dcaa582010-06-22 22:21:57 +020089 , keyBitmask(NULL), layoutMap(new KeyLayoutMap()), fd(-1), next(NULL) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080090}
91
92EventHub::device_t::~device_t() {
93 delete [] keyBitmask;
94 delete layoutMap;
95}
96
97EventHub::EventHub(void)
98 : mError(NO_INIT), mHaveFirstKeyboard(false), mFirstKeyboardId(0)
99 , mDevicesById(0), mNumDevicesById(0)
100 , mOpeningDevices(0), mClosingDevices(0)
Mike Lockwoodb4411062009-07-16 11:11:18 -0400101 , mDevices(0), mFDs(0), mFDCount(0), mOpened(false)
Jeff Brown82763072010-08-17 16:48:25 -0700102 , mInputBufferIndex(0), mInputBufferCount(0), mInputDeviceIndex(0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800103{
104 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
105#ifdef EV_SW
106 memset(mSwitches, 0, sizeof(mSwitches));
107#endif
108}
109
110/*
111 * Clean up.
112 */
113EventHub::~EventHub(void)
114{
115 release_wake_lock(WAKE_LOCK_ID);
116 // we should free stuff here...
117}
118
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800119status_t EventHub::errorCheck() const
120{
121 return mError;
122}
123
124String8 EventHub::getDeviceName(int32_t deviceId) const
125{
126 AutoMutex _l(mLock);
127 device_t* device = getDevice(deviceId);
128 if (device == NULL) return String8();
129 return device->name;
130}
131
132uint32_t EventHub::getDeviceClasses(int32_t deviceId) const
133{
134 AutoMutex _l(mLock);
135 device_t* device = getDevice(deviceId);
136 if (device == NULL) return 0;
137 return device->classes;
138}
139
Jeff Browne57e8952010-07-23 21:28:06 -0700140status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
141 RawAbsoluteAxisInfo* outAxisInfo) const {
142 outAxisInfo->valid = false;
143 outAxisInfo->minValue = 0;
144 outAxisInfo->maxValue = 0;
145 outAxisInfo->flat = 0;
146 outAxisInfo->fuzz = 0;
147
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800148 AutoMutex _l(mLock);
149 device_t* device = getDevice(deviceId);
150 if (device == NULL) return -1;
151
152 struct input_absinfo info;
153
Jens Gulin7dcaa582010-06-22 22:21:57 +0200154 if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
Jeff Browne57e8952010-07-23 21:28:06 -0700155 LOGW("Error reading absolute controller %d for device %s fd %d\n",
Jens Gulin7dcaa582010-06-22 22:21:57 +0200156 axis, device->name.string(), device->fd);
Jeff Browne57e8952010-07-23 21:28:06 -0700157 return -errno;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800158 }
Jeff Browne57e8952010-07-23 21:28:06 -0700159
160 if (info.minimum != info.maximum) {
161 outAxisInfo->valid = true;
162 outAxisInfo->minValue = info.minimum;
163 outAxisInfo->maxValue = info.maximum;
164 outAxisInfo->flat = info.flat;
165 outAxisInfo->fuzz = info.fuzz;
166 }
167 return OK;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800168}
169
Jeff Browne57e8952010-07-23 21:28:06 -0700170int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
Jeff Browne839a582010-04-22 18:58:52 -0700171 if (scanCode >= 0 && scanCode <= KEY_MAX) {
172 AutoMutex _l(mLock);
173
Jeff Browne57e8952010-07-23 21:28:06 -0700174 device_t* device = getDevice(deviceId);
175 if (device != NULL) {
176 return getScanCodeStateLocked(device, scanCode);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800177 }
178 }
Jeff Brown5c1ed842010-07-14 18:48:53 -0700179 return AKEY_STATE_UNKNOWN;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800180}
181
Jeff Browne839a582010-04-22 18:58:52 -0700182int32_t EventHub::getScanCodeStateLocked(device_t* device, int32_t scanCode) const {
Jeff Brown8575a872010-06-30 16:10:35 -0700183 uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
Jeff Browne839a582010-04-22 18:58:52 -0700184 memset(key_bitmask, 0, sizeof(key_bitmask));
Jens Gulin7dcaa582010-06-22 22:21:57 +0200185 if (ioctl(device->fd,
Jeff Browne839a582010-04-22 18:58:52 -0700186 EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700187 return test_bit(scanCode, key_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
Jeff Browne839a582010-04-22 18:58:52 -0700188 }
Jeff Brown5c1ed842010-07-14 18:48:53 -0700189 return AKEY_STATE_UNKNOWN;
Jeff Browne839a582010-04-22 18:58:52 -0700190}
191
Jeff Browne57e8952010-07-23 21:28:06 -0700192int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
193 AutoMutex _l(mLock);
Jeff Browne839a582010-04-22 18:58:52 -0700194
Jeff Browne57e8952010-07-23 21:28:06 -0700195 device_t* device = getDevice(deviceId);
196 if (device != NULL) {
197 return getKeyCodeStateLocked(device, keyCode);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800198 }
Jeff Brown5c1ed842010-07-14 18:48:53 -0700199 return AKEY_STATE_UNKNOWN;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800200}
201
Jeff Browne839a582010-04-22 18:58:52 -0700202int32_t EventHub::getKeyCodeStateLocked(device_t* device, int32_t keyCode) const {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800203 Vector<int32_t> scanCodes;
Jeff Browne839a582010-04-22 18:58:52 -0700204 device->layoutMap->findScancodes(keyCode, &scanCodes);
205
Jeff Brown8575a872010-06-30 16:10:35 -0700206 uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800207 memset(key_bitmask, 0, sizeof(key_bitmask));
Jens Gulin7dcaa582010-06-22 22:21:57 +0200208 if (ioctl(device->fd, EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800209 #if 0
210 for (size_t i=0; i<=KEY_MAX; i++) {
211 LOGI("(Scan code %d: down=%d)", i, test_bit(i, key_bitmask));
212 }
213 #endif
214 const size_t N = scanCodes.size();
215 for (size_t i=0; i<N && i<=KEY_MAX; i++) {
216 int32_t sc = scanCodes.itemAt(i);
217 //LOGI("Code %d: down=%d", sc, test_bit(sc, key_bitmask));
218 if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, key_bitmask)) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700219 return AKEY_STATE_DOWN;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800220 }
221 }
Jeff Brown5c1ed842010-07-14 18:48:53 -0700222 return AKEY_STATE_UP;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800223 }
Jeff Brown5c1ed842010-07-14 18:48:53 -0700224 return AKEY_STATE_UNKNOWN;
Jeff Browne839a582010-04-22 18:58:52 -0700225}
226
Jeff Browne57e8952010-07-23 21:28:06 -0700227int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
Jeff Browne839a582010-04-22 18:58:52 -0700228#ifdef EV_SW
229 if (sw >= 0 && sw <= SW_MAX) {
230 AutoMutex _l(mLock);
231
Jeff Browne839a582010-04-22 18:58:52 -0700232 device_t* device = getDevice(deviceId);
Jeff Browne57e8952010-07-23 21:28:06 -0700233 if (device != NULL) {
234 return getSwitchStateLocked(device, sw);
Jeff Browne839a582010-04-22 18:58:52 -0700235 }
Jeff Browne839a582010-04-22 18:58:52 -0700236 }
237#endif
Jeff Brown5c1ed842010-07-14 18:48:53 -0700238 return AKEY_STATE_UNKNOWN;
Jeff Browne839a582010-04-22 18:58:52 -0700239}
240
241int32_t EventHub::getSwitchStateLocked(device_t* device, int32_t sw) const {
Jeff Brown8575a872010-06-30 16:10:35 -0700242 uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
Jeff Browne839a582010-04-22 18:58:52 -0700243 memset(sw_bitmask, 0, sizeof(sw_bitmask));
Jens Gulin7dcaa582010-06-22 22:21:57 +0200244 if (ioctl(device->fd,
Jeff Browne839a582010-04-22 18:58:52 -0700245 EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700246 return test_bit(sw, sw_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
Jeff Browne839a582010-04-22 18:58:52 -0700247 }
Jeff Brown5c1ed842010-07-14 18:48:53 -0700248 return AKEY_STATE_UNKNOWN;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800249}
250
Jeff Browne57e8952010-07-23 21:28:06 -0700251bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
252 const int32_t* keyCodes, uint8_t* outFlags) const {
253 AutoMutex _l(mLock);
254
255 device_t* device = getDevice(deviceId);
256 if (device != NULL) {
257 return markSupportedKeyCodesLocked(device, numCodes, keyCodes, outFlags);
258 }
259 return false;
260}
261
262bool EventHub::markSupportedKeyCodesLocked(device_t* device, size_t numCodes,
263 const int32_t* keyCodes, uint8_t* outFlags) const {
264 if (device->layoutMap == NULL || device->keyBitmask == NULL) {
265 return false;
266 }
267
268 Vector<int32_t> scanCodes;
269 for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
270 scanCodes.clear();
271
272 status_t err = device->layoutMap->findScancodes(keyCodes[codeIndex], &scanCodes);
273 if (! err) {
274 // check the possible scan codes identified by the layout map against the
275 // map of codes actually emitted by the driver
276 for (size_t sc = 0; sc < scanCodes.size(); sc++) {
277 if (test_bit(scanCodes[sc], device->keyBitmask)) {
278 outFlags[codeIndex] = 1;
279 break;
280 }
281 }
282 }
283 }
284 return true;
285}
286
Dianne Hackbornc968c3a2009-07-14 12:06:54 -0700287status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode,
288 int32_t* outKeycode, uint32_t* outFlags) const
289{
290 AutoMutex _l(mLock);
291 device_t* device = getDevice(deviceId);
292
293 if (device != NULL && device->layoutMap != NULL) {
294 status_t err = device->layoutMap->map(scancode, outKeycode, outFlags);
295 if (err == NO_ERROR) {
296 return NO_ERROR;
297 }
298 }
299
300 if (mHaveFirstKeyboard) {
301 device = getDevice(mFirstKeyboardId);
302
303 if (device != NULL && device->layoutMap != NULL) {
304 status_t err = device->layoutMap->map(scancode, outKeycode, outFlags);
305 if (err == NO_ERROR) {
306 return NO_ERROR;
307 }
308 }
309 }
310
311 *outKeycode = 0;
312 *outFlags = 0;
313 return NAME_NOT_FOUND;
314}
315
Mike Lockwoodb4411062009-07-16 11:11:18 -0400316void EventHub::addExcludedDevice(const char* deviceName)
317{
318 String8 name(deviceName);
319 mExcludedDevices.push_back(name);
320}
321
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800322EventHub::device_t* EventHub::getDevice(int32_t deviceId) const
323{
324 if (deviceId == 0) deviceId = mFirstKeyboardId;
325 int32_t id = deviceId & ID_MASK;
326 if (id >= mNumDevicesById || id < 0) return NULL;
327 device_t* dev = mDevicesById[id].device;
Dianne Hackbornc3aa00b2009-03-25 16:21:55 -0700328 if (dev == NULL) return NULL;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800329 if (dev->id == deviceId) {
330 return dev;
331 }
332 return NULL;
333}
334
Jeff Browne57e8952010-07-23 21:28:06 -0700335bool EventHub::getEvent(RawEvent* outEvent)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800336{
Jeff Browne57e8952010-07-23 21:28:06 -0700337 outEvent->deviceId = 0;
338 outEvent->type = 0;
339 outEvent->scanCode = 0;
340 outEvent->keyCode = 0;
341 outEvent->flags = 0;
342 outEvent->value = 0;
343 outEvent->when = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800344
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800345 // Note that we only allow one caller to getEvent(), so don't need
346 // to do locking here... only when adding/removing devices.
Mike Lockwoodb4411062009-07-16 11:11:18 -0400347
348 if (!mOpened) {
349 mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;
350 mOpened = true;
351 }
352
Jeff Brown82763072010-08-17 16:48:25 -0700353 for (;;) {
354 // Report any devices that had last been added/removed.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800355 if (mClosingDevices != NULL) {
356 device_t* device = mClosingDevices;
357 LOGV("Reporting device closed: id=0x%x, name=%s\n",
358 device->id, device->path.string());
359 mClosingDevices = device->next;
Jeff Browne57e8952010-07-23 21:28:06 -0700360 if (device->id == mFirstKeyboardId) {
361 outEvent->deviceId = 0;
362 } else {
363 outEvent->deviceId = device->id;
364 }
365 outEvent->type = DEVICE_REMOVED;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800366 delete device;
367 return true;
368 }
Jeff Browne57e8952010-07-23 21:28:06 -0700369
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800370 if (mOpeningDevices != NULL) {
371 device_t* device = mOpeningDevices;
372 LOGV("Reporting device opened: id=0x%x, name=%s\n",
373 device->id, device->path.string());
374 mOpeningDevices = device->next;
Jeff Browne57e8952010-07-23 21:28:06 -0700375 if (device->id == mFirstKeyboardId) {
376 outEvent->deviceId = 0;
377 } else {
378 outEvent->deviceId = device->id;
379 }
380 outEvent->type = DEVICE_ADDED;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800381 return true;
382 }
383
Jeff Brown82763072010-08-17 16:48:25 -0700384 // Grab the next input event.
385 for (;;) {
386 // Consume buffered input events, if any.
387 if (mInputBufferIndex < mInputBufferCount) {
388 const struct input_event& iev = mInputBufferData[mInputBufferIndex++];
389 const device_t* device = mDevices[mInputDeviceIndex];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800390
Jeff Brown82763072010-08-17 16:48:25 -0700391 LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, v=%d", device->path.string(),
392 (int) iev.time.tv_sec, (int) iev.time.tv_usec, iev.type, iev.code, iev.value);
393 if (device->id == mFirstKeyboardId) {
394 outEvent->deviceId = 0;
395 } else {
396 outEvent->deviceId = device->id;
397 }
398 outEvent->type = iev.type;
399 outEvent->scanCode = iev.code;
400 if (iev.type == EV_KEY) {
401 status_t err = device->layoutMap->map(iev.code,
402 & outEvent->keyCode, & outEvent->flags);
403 LOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n",
404 iev.code, outEvent->keyCode, outEvent->flags, err);
405 if (err != 0) {
406 outEvent->keyCode = AKEYCODE_UNKNOWN;
407 outEvent->flags = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800408 }
Jeff Brown82763072010-08-17 16:48:25 -0700409 } else {
410 outEvent->keyCode = iev.code;
411 }
412 outEvent->value = iev.value;
413
414 // Use an event timestamp in the same timebase as
415 // java.lang.System.nanoTime() and android.os.SystemClock.uptimeMillis()
416 // as expected by the rest of the system.
417 outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
418 return true;
419 }
420
421 // Finish reading all events from devices identified in previous poll().
422 // This code assumes that mInputDeviceIndex is initially 0 and that the
423 // revents member of pollfd is initialized to 0 when the device is first added.
424 // Since mFDs[0] is used for inotify, we process regular events starting at index 1.
425 mInputDeviceIndex += 1;
426 if (mInputDeviceIndex >= mFDCount) {
427 mInputDeviceIndex = 0;
428 break;
429 }
430
431 const struct pollfd &pfd = mFDs[mInputDeviceIndex];
432 if (pfd.revents & POLLIN) {
433 int32_t readSize = read(pfd.fd, mInputBufferData,
434 sizeof(struct input_event) * INPUT_BUFFER_SIZE);
435 if (readSize < 0) {
436 if (errno != EAGAIN && errno != EINTR) {
437 LOGW("could not get event (errno=%d)", errno);
438 }
439 } else if ((readSize % sizeof(struct input_event)) != 0) {
440 LOGE("could not get event (wrong size: %d)", readSize);
441 } else {
442 mInputBufferCount = readSize / sizeof(struct input_event);
443 mInputBufferIndex = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800444 }
445 }
446 }
Jeff Brown82763072010-08-17 16:48:25 -0700447
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800448 // read_notify() will modify mFDs and mFDCount, so this must be done after
449 // processing all other events.
450 if(mFDs[0].revents & POLLIN) {
451 read_notify(mFDs[0].fd);
452 }
Jeff Brown82763072010-08-17 16:48:25 -0700453
454 // Poll for events. Mind the wake lock dance!
455 // We hold a wake lock at all times except during poll(). This works due to some
456 // subtle choreography. When a device driver has pending (unread) events, it acquires
457 // a kernel wake lock. However, once the last pending event has been read, the device
458 // driver will release the kernel wake lock. To prevent the system from going to sleep
459 // when this happens, the EventHub holds onto its own user wake lock while the client
460 // is processing events. Thus the system can only sleep if there are no events
461 // pending or currently being processed.
462 release_wake_lock(WAKE_LOCK_ID);
463
464 int pollResult = poll(mFDs, mFDCount, -1);
465
466 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
467
468 if (pollResult <= 0) {
469 if (errno != EINTR) {
470 LOGW("select failed (errno=%d)\n", errno);
471 usleep(100000);
472 }
473 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800474 }
475}
476
477/*
478 * Open the platform-specific input device.
479 */
480bool EventHub::openPlatformInput(void)
481{
482 /*
483 * Open platform-specific input device(s).
484 */
485 int res;
486
487 mFDCount = 1;
488 mFDs = (pollfd *)calloc(1, sizeof(mFDs[0]));
489 mDevices = (device_t **)calloc(1, sizeof(mDevices[0]));
490 mFDs[0].events = POLLIN;
Jeff Brown82763072010-08-17 16:48:25 -0700491 mFDs[0].revents = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800492 mDevices[0] = NULL;
493#ifdef HAVE_INOTIFY
494 mFDs[0].fd = inotify_init();
495 res = inotify_add_watch(mFDs[0].fd, device_path, IN_DELETE | IN_CREATE);
496 if(res < 0) {
497 LOGE("could not add watch for %s, %s\n", device_path, strerror(errno));
498 }
499#else
500 /*
501 * The code in EventHub::getEvent assumes that mFDs[0] is an inotify fd.
502 * We allocate space for it and set it to something invalid.
503 */
504 mFDs[0].fd = -1;
505#endif
506
507 res = scan_dir(device_path);
508 if(res < 0) {
509 LOGE("scan dir failed for %s\n", device_path);
510 //open_device("/dev/input/event0");
511 }
512
513 return true;
514}
515
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800516// ----------------------------------------------------------------------------
517
Jeff Brown8575a872010-06-30 16:10:35 -0700518static bool containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex) {
519 const uint8_t* end = array + endIndex;
520 array += startIndex;
521 while (array != end) {
522 if (*(array++) != 0) {
523 return true;
524 }
525 }
526 return false;
527}
528
529static const int32_t GAMEPAD_KEYCODES[] = {
530 AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C,
531 AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z,
532 AKEYCODE_BUTTON_L1, AKEYCODE_BUTTON_R1,
533 AKEYCODE_BUTTON_L2, AKEYCODE_BUTTON_R2,
534 AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR,
535 AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE
536};
537
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800538int EventHub::open_device(const char *deviceName)
539{
540 int version;
541 int fd;
542 struct pollfd *new_mFDs;
543 device_t **new_devices;
544 char **new_device_names;
545 char name[80];
546 char location[80];
547 char idstr[80];
548 struct input_id id;
549
550 LOGV("Opening device: %s", deviceName);
551
552 AutoMutex _l(mLock);
Nick Pellyc81bb202010-01-20 19:36:49 -0800553
Nick Pelly1b5cf322010-01-26 10:27:15 -0800554 fd = open(deviceName, O_RDWR);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800555 if(fd < 0) {
556 LOGE("could not open %s, %s\n", deviceName, strerror(errno));
557 return -1;
558 }
559
560 if(ioctl(fd, EVIOCGVERSION, &version)) {
561 LOGE("could not get driver version for %s, %s\n", deviceName, strerror(errno));
562 return -1;
563 }
564 if(ioctl(fd, EVIOCGID, &id)) {
565 LOGE("could not get driver id for %s, %s\n", deviceName, strerror(errno));
566 return -1;
567 }
568 name[sizeof(name) - 1] = '\0';
569 location[sizeof(location) - 1] = '\0';
570 idstr[sizeof(idstr) - 1] = '\0';
571 if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
572 //fprintf(stderr, "could not get device name for %s, %s\n", deviceName, strerror(errno));
573 name[0] = '\0';
574 }
Mike Lockwood24a7e042009-07-17 00:10:10 -0400575
576 // check to see if the device is on our excluded list
577 List<String8>::iterator iter = mExcludedDevices.begin();
578 List<String8>::iterator end = mExcludedDevices.end();
579 for ( ; iter != end; iter++) {
580 const char* test = *iter;
581 if (strcmp(name, test) == 0) {
582 LOGI("ignoring event id %s driver %s\n", deviceName, test);
583 close(fd);
Mike Lockwood24a7e042009-07-17 00:10:10 -0400584 return -1;
585 }
586 }
587
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800588 if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) {
589 //fprintf(stderr, "could not get location for %s, %s\n", deviceName, strerror(errno));
590 location[0] = '\0';
591 }
592 if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) {
593 //fprintf(stderr, "could not get idstring for %s, %s\n", deviceName, strerror(errno));
594 idstr[0] = '\0';
595 }
596
Jeff Brown82763072010-08-17 16:48:25 -0700597 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
598 LOGE("Error %d making device file descriptor non-blocking.", errno);
599 close(fd);
600 return -1;
601 }
602
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800603 int devid = 0;
604 while (devid < mNumDevicesById) {
605 if (mDevicesById[devid].device == NULL) {
606 break;
607 }
608 devid++;
609 }
610 if (devid >= mNumDevicesById) {
611 device_ent* new_devids = (device_ent*)realloc(mDevicesById,
612 sizeof(mDevicesById[0]) * (devid + 1));
613 if (new_devids == NULL) {
614 LOGE("out of memory");
615 return -1;
616 }
617 mDevicesById = new_devids;
618 mNumDevicesById = devid+1;
619 mDevicesById[devid].device = NULL;
620 mDevicesById[devid].seq = 0;
621 }
622
623 mDevicesById[devid].seq = (mDevicesById[devid].seq+(1<<SEQ_SHIFT))&SEQ_MASK;
624 if (mDevicesById[devid].seq == 0) {
625 mDevicesById[devid].seq = 1<<SEQ_SHIFT;
626 }
627
628 new_mFDs = (pollfd*)realloc(mFDs, sizeof(mFDs[0]) * (mFDCount + 1));
629 new_devices = (device_t**)realloc(mDevices, sizeof(mDevices[0]) * (mFDCount + 1));
630 if (new_mFDs == NULL || new_devices == NULL) {
631 LOGE("out of memory");
632 return -1;
633 }
634 mFDs = new_mFDs;
635 mDevices = new_devices;
636
637#if 0
638 LOGI("add device %d: %s\n", mFDCount, deviceName);
639 LOGI(" bus: %04x\n"
640 " vendor %04x\n"
641 " product %04x\n"
642 " version %04x\n",
643 id.bustype, id.vendor, id.product, id.version);
644 LOGI(" name: \"%s\"\n", name);
645 LOGI(" location: \"%s\"\n"
646 " id: \"%s\"\n", location, idstr);
647 LOGI(" version: %d.%d.%d\n",
648 version >> 16, (version >> 8) & 0xff, version & 0xff);
649#endif
650
Iliyan Malchev34193b32009-08-06 14:50:08 -0700651 device_t* device = new device_t(devid|mDevicesById[devid].seq, deviceName, name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800652 if (device == NULL) {
653 LOGE("out of memory");
654 return -1;
655 }
656
Jens Gulin7dcaa582010-06-22 22:21:57 +0200657 device->fd = fd;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800658 mFDs[mFDCount].fd = fd;
659 mFDs[mFDCount].events = POLLIN;
Jeff Brown82763072010-08-17 16:48:25 -0700660 mFDs[mFDCount].revents = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800661
Jeff Brown8575a872010-06-30 16:10:35 -0700662 // Figure out the kinds of events the device reports.
Dianne Hackbornc5917362009-08-04 05:49:43 -0700663
Jeff Brown8575a872010-06-30 16:10:35 -0700664 uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800665 memset(key_bitmask, 0, sizeof(key_bitmask));
Jeff Brown8575a872010-06-30 16:10:35 -0700666
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800667 LOGV("Getting keys...");
668 if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
669 //LOGI("MAP\n");
Jeff Brown8575a872010-06-30 16:10:35 -0700670 //for (int i = 0; i < sizeof(key_bitmask); i++) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800671 // LOGI("%d: 0x%02x\n", i, key_bitmask[i]);
672 //}
Jeff Brown8575a872010-06-30 16:10:35 -0700673
674 // See if this is a keyboard. Ignore everything in the button range except for
675 // gamepads which are also considered keyboards.
676 if (containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC))
677 || containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_GAMEPAD),
678 sizeof_bit_array(BTN_DIGI))
679 || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK),
680 sizeof_bit_array(KEY_MAX + 1))) {
681 device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
682
Dianne Hackbornc5917362009-08-04 05:49:43 -0700683 device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800684 if (device->keyBitmask != NULL) {
685 memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
686 } else {
687 delete device;
688 LOGE("out of memory allocating key bitmask");
689 return -1;
690 }
691 }
692 }
Dianne Hackbornc5917362009-08-04 05:49:43 -0700693
Jeff Brown8575a872010-06-30 16:10:35 -0700694 // See if this is a trackball (or mouse).
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800695 if (test_bit(BTN_MOUSE, key_bitmask)) {
Jeff Brown8575a872010-06-30 16:10:35 -0700696 uint8_t rel_bitmask[sizeof_bit_array(REL_MAX + 1)];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800697 memset(rel_bitmask, 0, sizeof(rel_bitmask));
698 LOGV("Getting relative controllers...");
Jeff Brown8575a872010-06-30 16:10:35 -0700699 if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800700 if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
Jeff Browne839a582010-04-22 18:58:52 -0700701 device->classes |= INPUT_DEVICE_CLASS_TRACKBALL;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800702 }
703 }
704 }
Jeff Brown8575a872010-06-30 16:10:35 -0700705
706 // See if this is a touch pad.
707 uint8_t abs_bitmask[sizeof_bit_array(ABS_MAX + 1)];
Dianne Hackbornc5917362009-08-04 05:49:43 -0700708 memset(abs_bitmask, 0, sizeof(abs_bitmask));
709 LOGV("Getting absolute controllers...");
Jeff Brown8575a872010-06-30 16:10:35 -0700710 if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0) {
711 // Is this a new modern multi-touch driver?
712 if (test_bit(ABS_MT_TOUCH_MAJOR, abs_bitmask)
713 && test_bit(ABS_MT_POSITION_X, abs_bitmask)
714 && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
715 device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT;
716
717 // Is this an old style single-touch driver?
718 } else if (test_bit(BTN_TOUCH, key_bitmask)
719 && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
720 device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN;
721 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800722 }
723
724#ifdef EV_SW
725 // figure out the switches this device reports
Jeff Brown8575a872010-06-30 16:10:35 -0700726 uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800727 memset(sw_bitmask, 0, sizeof(sw_bitmask));
Jeff Browne57e8952010-07-23 21:28:06 -0700728 bool hasSwitches = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800729 if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
730 for (int i=0; i<EV_SW; i++) {
731 //LOGI("Device 0x%x sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
732 if (test_bit(i, sw_bitmask)) {
Jeff Browne57e8952010-07-23 21:28:06 -0700733 hasSwitches = true;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800734 if (mSwitches[i] == 0) {
735 mSwitches[i] = device->id;
736 }
737 }
738 }
739 }
Jeff Browne57e8952010-07-23 21:28:06 -0700740 if (hasSwitches) {
741 device->classes |= INPUT_DEVICE_CLASS_SWITCH;
742 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800743#endif
744
Jeff Browne839a582010-04-22 18:58:52 -0700745 if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
Iliyan Malchev34193b32009-08-06 14:50:08 -0700746 char tmpfn[sizeof(name)];
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800747 char keylayoutFilename[300];
748
749 // a more descriptive name
Iliyan Malchev34193b32009-08-06 14:50:08 -0700750 device->name = name;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800751
752 // replace all the spaces with underscores
Iliyan Malchev34193b32009-08-06 14:50:08 -0700753 strcpy(tmpfn, name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800754 for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' '))
755 *p = '_';
756
757 // find the .kl file we need for this device
758 const char* root = getenv("ANDROID_ROOT");
759 snprintf(keylayoutFilename, sizeof(keylayoutFilename),
760 "%s/usr/keylayout/%s.kl", root, tmpfn);
761 bool defaultKeymap = false;
762 if (access(keylayoutFilename, R_OK)) {
763 snprintf(keylayoutFilename, sizeof(keylayoutFilename),
764 "%s/usr/keylayout/%s", root, "qwerty.kl");
765 defaultKeymap = true;
766 }
Jeff Brown8575a872010-06-30 16:10:35 -0700767 status_t status = device->layoutMap->load(keylayoutFilename);
768 if (status) {
769 LOGE("Error %d loading key layout.", status);
770 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800771
772 // tell the world about the devname (the descriptive name)
Dianne Hackborn71c3eb22010-03-02 17:19:29 -0800773 if (!mHaveFirstKeyboard && !defaultKeymap && strstr(name, "-keypad")) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800774 // the built-in keyboard has a well-known device ID of 0,
775 // this device better not go away.
776 mHaveFirstKeyboard = true;
777 mFirstKeyboardId = device->id;
Dianne Hackborn71c3eb22010-03-02 17:19:29 -0800778 property_set("hw.keyboards.0.devname", name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800779 } else {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800780 // ensure mFirstKeyboardId is set to -something-.
781 if (mFirstKeyboardId == 0) {
782 mFirstKeyboardId = device->id;
783 }
784 }
785 char propName[100];
Dianne Hackborn71c3eb22010-03-02 17:19:29 -0800786 sprintf(propName, "hw.keyboards.%u.devname", device->id);
Iliyan Malchev34193b32009-08-06 14:50:08 -0700787 property_set(propName, name);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800788
Dianne Hackbornc5917362009-08-04 05:49:43 -0700789 // 'Q' key support = cheap test of whether this is an alpha-capable kbd
Jeff Brown8575a872010-06-30 16:10:35 -0700790 if (hasKeycode(device, AKEYCODE_Q)) {
Jeff Browne839a582010-04-22 18:58:52 -0700791 device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
Dianne Hackbornc5917362009-08-04 05:49:43 -0700792 }
793
Jeff Brown8575a872010-06-30 16:10:35 -0700794 // See if this device has a DPAD.
795 if (hasKeycode(device, AKEYCODE_DPAD_UP) &&
796 hasKeycode(device, AKEYCODE_DPAD_DOWN) &&
797 hasKeycode(device, AKEYCODE_DPAD_LEFT) &&
798 hasKeycode(device, AKEYCODE_DPAD_RIGHT) &&
799 hasKeycode(device, AKEYCODE_DPAD_CENTER)) {
Jeff Browne839a582010-04-22 18:58:52 -0700800 device->classes |= INPUT_DEVICE_CLASS_DPAD;
Dianne Hackbornc5917362009-08-04 05:49:43 -0700801 }
802
Jeff Brown8575a872010-06-30 16:10:35 -0700803 // See if this device has a gamepad.
804 for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES); i++) {
805 if (hasKeycode(device, GAMEPAD_KEYCODES[i])) {
806 device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
807 break;
808 }
809 }
810
Dianne Hackborn71c3eb22010-03-02 17:19:29 -0800811 LOGI("New keyboard: device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
812 device->id, name, propName, keylayoutFilename);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800813 }
814
Sean McNeil2e7a5302010-06-23 16:00:37 +0700815 // If the device isn't recognized as something we handle, don't monitor it.
816 if (device->classes == 0) {
817 LOGV("Dropping device %s %p, id = %d\n", deviceName, device, devid);
818 close(fd);
819 delete device;
820 return -1;
821 }
822
Dianne Hackbornc5917362009-08-04 05:49:43 -0700823 LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
824 deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes);
825
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800826 LOGV("Adding device %s %p at %d, id = %d, classes = 0x%x\n",
827 deviceName, device, mFDCount, devid, device->classes);
828
829 mDevicesById[devid].device = device;
830 device->next = mOpeningDevices;
831 mOpeningDevices = device;
832 mDevices[mFDCount] = device;
833
834 mFDCount++;
835 return 0;
836}
837
Dianne Hackbornc5917362009-08-04 05:49:43 -0700838bool EventHub::hasKeycode(device_t* device, int keycode) const
839{
840 if (device->keyBitmask == NULL || device->layoutMap == NULL) {
841 return false;
842 }
843
844 Vector<int32_t> scanCodes;
845 device->layoutMap->findScancodes(keycode, &scanCodes);
846 const size_t N = scanCodes.size();
847 for (size_t i=0; i<N && i<=KEY_MAX; i++) {
848 int32_t sc = scanCodes.itemAt(i);
849 if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) {
850 return true;
851 }
852 }
853
854 return false;
855}
856
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800857int EventHub::close_device(const char *deviceName)
858{
859 AutoMutex _l(mLock);
860
861 int i;
862 for(i = 1; i < mFDCount; i++) {
863 if(strcmp(mDevices[i]->path.string(), deviceName) == 0) {
864 //LOGD("remove device %d: %s\n", i, deviceName);
865 device_t* device = mDevices[i];
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700866
867 LOGI("Removed device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
868 device->path.string(), device->name.string(), device->id,
869 mNumDevicesById, mFDCount, mFDs[i].fd, device->classes);
870
871 // Clear this device's entry.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800872 int index = (device->id&ID_MASK);
873 mDevicesById[index].device = NULL;
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700874
875 // Close the file descriptor and compact the fd array.
Mike Lockwood07549f92009-08-28 13:29:06 -0700876 close(mFDs[i].fd);
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700877 int count = mFDCount - i - 1;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800878 memmove(mDevices + i, mDevices + i + 1, sizeof(mDevices[0]) * count);
879 memmove(mFDs + i, mFDs + i + 1, sizeof(mFDs[0]) * count);
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700880 mFDCount--;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800881
882#ifdef EV_SW
883 for (int j=0; j<EV_SW; j++) {
884 if (mSwitches[j] == device->id) {
885 mSwitches[j] = 0;
886 }
887 }
888#endif
889
890 device->next = mClosingDevices;
891 mClosingDevices = device;
892
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800893 if (device->id == mFirstKeyboardId) {
894 LOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
895 device->path.string(), mFirstKeyboardId);
896 mFirstKeyboardId = 0;
Dianne Hackborn71c3eb22010-03-02 17:19:29 -0800897 property_set("hw.keyboards.0.devname", NULL);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800898 }
899 // clear the property
900 char propName[100];
Dianne Hackborn71c3eb22010-03-02 17:19:29 -0800901 sprintf(propName, "hw.keyboards.%u.devname", device->id);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800902 property_set(propName, NULL);
903 return 0;
904 }
905 }
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700906 LOGE("remove device: %s not found\n", deviceName);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800907 return -1;
908}
909
910int EventHub::read_notify(int nfd)
911{
912#ifdef HAVE_INOTIFY
913 int res;
914 char devname[PATH_MAX];
915 char *filename;
916 char event_buf[512];
917 int event_size;
918 int event_pos = 0;
919 struct inotify_event *event;
920
Dianne Hackborn39bf9182009-09-01 19:01:50 -0700921 LOGV("EventHub::read_notify nfd: %d\n", nfd);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800922 res = read(nfd, event_buf, sizeof(event_buf));
923 if(res < (int)sizeof(*event)) {
924 if(errno == EINTR)
925 return 0;
926 LOGW("could not get event, %s\n", strerror(errno));
927 return 1;
928 }
929 //printf("got %d bytes of event information\n", res);
930
931 strcpy(devname, device_path);
932 filename = devname + strlen(devname);
933 *filename++ = '/';
934
935 while(res >= (int)sizeof(*event)) {
936 event = (struct inotify_event *)(event_buf + event_pos);
937 //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");
938 if(event->len) {
939 strcpy(filename, event->name);
940 if(event->mask & IN_CREATE) {
941 open_device(devname);
942 }
943 else {
944 close_device(devname);
945 }
946 }
947 event_size = sizeof(*event) + event->len;
948 res -= event_size;
949 event_pos += event_size;
950 }
951#endif
952 return 0;
953}
954
955
956int EventHub::scan_dir(const char *dirname)
957{
958 char devname[PATH_MAX];
959 char *filename;
960 DIR *dir;
961 struct dirent *de;
962 dir = opendir(dirname);
963 if(dir == NULL)
964 return -1;
965 strcpy(devname, dirname);
966 filename = devname + strlen(devname);
967 *filename++ = '/';
968 while((de = readdir(dir))) {
969 if(de->d_name[0] == '.' &&
970 (de->d_name[1] == '\0' ||
971 (de->d_name[1] == '.' && de->d_name[2] == '\0')))
972 continue;
973 strcpy(filename, de->d_name);
974 open_device(devname);
975 }
976 closedir(dir);
977 return 0;
978}
979
980}; // namespace android