int EventHub::getKeycodeState(int32_t deviceId, int code) const { AutoMutex _l(mLock); device_t* device = getDevice(deviceId); if (device == NULL || device->layoutMap == NULL) return -1; Vector<int32_t> scanCodes; device->layoutMap->findScancodes(code, &scanCodes); uint8_t key_bitmask[(KEY_MAX+7)/8]; memset(key_bitmask, 0, sizeof(key_bitmask)); if (ioctl(mFDs[id_to_index(device->id)].fd, EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) { #if 0 for (size_t i=0; i<=KEY_MAX; i++) { LOGI("(Scan code %d: down=%d)", i, test_bit(i, key_bitmask)); } #endif const size_t N = scanCodes.size(); for (size_t i=0; i<N && i<=KEY_MAX; i++) { int32_t sc = scanCodes.itemAt(i); //LOGI("Code %d: down=%d", sc, test_bit(sc, key_bitmask)); if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, key_bitmask)) { return 1; } } } return 0; }
int ev_sync_key_state(ev_set_key_callback set_key_cb, void* data) { unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)]; for (size_t i = 0; i < ev_dev_count; ++i) { memset(ev_bits, 0, sizeof(ev_bits)); memset(key_bits, 0, sizeof(key_bits)); if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) { continue; } if (!test_bit(EV_KEY, ev_bits)) { continue; } if (ioctl(ev_fdinfo[i].fd, EVIOCGKEY(sizeof(key_bits)), key_bits) == -1) { continue; } for (int code = 0; code <= KEY_MAX; code++) { if (test_bit(code, key_bits)) { set_key_cb(code, 1, data); } } } return 0; }
void evdev_notify_keyboard_focus(struct weston_seat *seat, struct wl_list *evdev_devices) { struct evdev_device *device; struct wl_array keys; unsigned int i, set; char evdev_keys[(KEY_CNT + 7) / 8]; char all_keys[(KEY_CNT + 7) / 8]; uint32_t *k; int ret; if (!seat->keyboard) return; memset(all_keys, 0, sizeof all_keys); wl_list_for_each(device, evdev_devices, link) { memset(evdev_keys, 0, sizeof evdev_keys); ret = ioctl(device->fd, EVIOCGKEY(sizeof evdev_keys), evdev_keys); if (ret < 0) { weston_log("failed to get keys for device %s\n", device->devnode); continue; } for (i = 0; i < ARRAY_LENGTH(evdev_keys); i++) all_keys[i] |= evdev_keys[i]; }
int ev_sync_key_state(ev_set_key_callback set_key_cb, void *data) { unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)]; unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; unsigned i; int ret; for (i = 0; i < ev_dev_count; i++) { int code; memset(key_bits, 0, sizeof(key_bits)); memset(ev_bits, 0, sizeof(ev_bits)); ret = ioctl(ev_fds[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits); if (ret < 0 || !test_bit(EV_KEY, ev_bits)) continue; ret = ioctl(ev_fds[i].fd, EVIOCGKEY(sizeof(key_bits)), key_bits); if (ret < 0) continue; for (code = 0; code <= KEY_MAX; code++) { if (test_bit(code, key_bits)) set_key_cb(code, 1, data); } } return 0; }
void uxkb_dev_wake_up(struct uterm_input_dev *dev) { uint32_t code; char *old_bits, cur_bits[sizeof(dev->key_state_bits)]; char old_bit, cur_bit; old_bits = dev->key_state_bits; memset(cur_bits, 0, sizeof(cur_bits)); errno = 0; ioctl(dev->rfd, EVIOCGKEY(sizeof(cur_bits)), cur_bits); if (errno) { log_warn("failed to get current keyboard state (%d): %m", errno); return; } for (code = 0; code < KEY_CNT; code++) { old_bit = (old_bits[code / 8] & (1 << (code % 8))); cur_bit = (cur_bits[code / 8] & (1 << (code % 8))); if (old_bit == cur_bit) continue; xkb_state_update_key(dev->state, code + EVDEV_KEYCODE_OFFSET, cur_bit ? XKB_KEY_DOWN : XKB_KEY_UP); } uxkb_dev_update_keyboard_leds(dev); }
int rdKey(int fd, int key) {//faster not to open file every time // const char *dev = "/dev/input/by-path/platform-i8042-serio-0-event-kbd"; // int keyboard = open(dev, O_RDONLY); char arr[(KEY_MAX+7)/8]; memset(arr, 0, sizeof(arr)); ioctl(fd, EVIOCGKEY(sizeof(arr)), arr); return !!(arr[key/8] & (1<<(key % 8))); }
int32_t EventHub::getScanCodeStateLocked(device_t* device, int32_t scanCode) const { uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)]; memset(key_bitmask, 0, sizeof(key_bitmask)); if (ioctl(device->fd, EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) { return test_bit(scanCode, key_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP; } return AKEY_STATE_UNKNOWN; }
JNIEXPORT void JNICALL Java_net_java_games_input_LinuxEventDevice_nGetKeyStates(JNIEnv *env, jclass unused, jlong fd_address, jbyteArray bits_array) { int fd = (int)fd_address; jsize len = (*env)->GetArrayLength(env, bits_array); jbyte *bits = (*env)->GetByteArrayElements(env, bits_array, NULL); if (bits == NULL) return; int res = ioctl(fd, EVIOCGKEY(len), bits); (*env)->ReleaseByteArrayElements(env, bits_array, bits, 0); if (res == -1) throwIOException(env, "Failed to get device key states (%d)\n", errno); }
int is_any_key_pressed(void) { size_t n, i; unsigned long keys[BITS_TO_LONGS(KEY_CNT)]; for(n = 0; n < ev_count; ++n) { if(ioctl(ev_fds[n].fd, EVIOCGKEY(KEY_CNT), keys) >= 0) for(i = 0; i < BITS_TO_LONGS(KEY_CNT); ++i) if(keys[i] != 0) return 1; } return 0; }
static PyObject * ioctl_EVIOCG_bits(PyObject *self, PyObject *args) { int max, fd, evtype, ret; ret = PyArg_ParseTuple(args, "ii", &fd, &evtype); if (!ret) return NULL; switch (evtype) { case EV_LED: max = LED_MAX; break; case EV_SND: max = SND_MAX; break; case EV_KEY: max = KEY_MAX; break; case EV_SW: max = SW_MAX; break; default: return NULL; } char bytes[(max+7)/8]; memset(bytes, 0, sizeof bytes); switch (evtype) { case EV_LED: ret = ioctl(fd, EVIOCGLED(sizeof(bytes)), &bytes); break; case EV_SND: ret = ioctl(fd, EVIOCGSND(sizeof(bytes)), &bytes); break; case EV_KEY: ret = ioctl(fd, EVIOCGKEY(sizeof(bytes)), &bytes); break; case EV_SW: ret = ioctl(fd, EVIOCGSW(sizeof(bytes)), &bytes); break; } if (ret == -1) return NULL; PyObject* res = PyList_New(0); for (int i=0; i<max; i++) { if (test_bit(bytes, i)) { PyList_Append(res, Py_BuildValue("i", i)); } } return res; }
bool KeyDetection::_isF10pressed(int fd) { u_int8_t keymap[KEY_MAX/8+1] = {0}; if (ioctl(fd, EVIOCGKEY(sizeof(keymap)), &keymap) == -1) { qDebug() << "Error getting global key state"; } bool pressed = test_bit(KEY_F10, keymap) || test_bit(KEY_LEFTSHIFT, keymap) || test_bit(KEY_RIGHTSHIFT, keymap); //qDebug() << "Key press detection:" << pressed; return pressed; }
int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const { if (scanCode >= 0 && scanCode <= KEY_MAX) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && test_bit(scanCode, device->keyBitmask)) { uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)]; memset(keyState, 0, sizeof(keyState)); if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 0) { return test_bit(scanCode, keyState) ? AKEY_STATE_DOWN : AKEY_STATE_UP; } } } return AKEY_STATE_UNKNOWN; }
size_t ev3_read_keys( uint8_t *buf ) { int f; uint8_t keyb[( KEY_MAX + 7 ) / 8 ]; f = open( GPIO_KEYS_PATH, O_RDONLY ); if ( f < 0 ) return ( 0 ); ioctl( f, EVIOCGKEY( sizeof( keyb )), &keyb ); *buf = _TEST_KEY( UP, UP ) | _TEST_KEY( DOWN, DOWN ) | _TEST_KEY( LEFT, LEFT ) | _TEST_KEY( RIGHT, RIGHT ) | _TEST_KEY( ENTER, CENTER ) | _TEST_KEY( BACKSPACE, BACK ); close( f ); return ( sizeof( uint8_t )); }
int main ( int argc, char *argv[], char *env[] ) { int deviceFile = open("/dev/input/by-path/platform-i8042-serio-0-event-kbd", O_RDONLY); //opening device file. ATTENTION: you have to have access to it. Easiest way is to "sudo ./a.out". if(deviceFile < 0) { printf("Device file not opened. Most likely you don't have access to it, try to run your program with sudo"); } memset(keys, 0, sizeof(keys)); //just in case, not really necessary struct Player player; player.x = width / 2; while(1) { int x; int y; for(y = 0; y < height; y++) { printf("\n"); } ioctl (deviceFile, EVIOCGKEY(sizeof keys), &keys); //update keyboard state if(testKey(leftKey) && player.x > 0) player.x--; if(testKey(rightKey) && player.x < width - 1) player.x++; for(x = 0; x < width; x++) { if(x == player.x) { printf("@"); } else if(x > 0 || x < width - 1) { printf("."); }else { printf("#"); } } printf("\n\n"); //to avoid screen tearing int w; for(w = 0; w < 10000000; w++); } return 0; }
void release_keys(int fd, int input_fd) { int i, j; unsigned char keys[KEY_MAX/8 + 1]; memset(keys, 0, sizeof keys); ioctl(fd, EVIOCGKEY(sizeof keys), keys); for(i = 0; i < sizeof keys; i++) { for(j = 0; j < 8; j++) { if(keys[i] & (1 << j)) { sendkey(input_fd, i*8 + j, 0); } } } }
int EventHub::getScancodeState(int32_t deviceId, int code) const { AutoMutex _l(mLock); device_t* device = getDevice(deviceId); if (device == NULL) return -1; if (code >= 0 && code <= KEY_MAX) { uint8_t key_bitmask[(KEY_MAX+7)/8]; memset(key_bitmask, 0, sizeof(key_bitmask)); if (ioctl(mFDs[id_to_index(device->id)].fd, EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) { return test_bit(code, key_bitmask) ? 1 : 0; } } return -1; }
int32_t ev3_button_pressed(enum ev3_button_identifier button) { uint8_t keys[96]; lseek(__ev3_button_fd,0,SEEK_SET); ioctl (__ev3_button_fd, EVIOCGKEY(sizeof keys), &keys); switch (button) { case BUTTON_LEFT: return keys[KEY_LEFT >> 3] & (1 << (KEY_LEFT & 7))?0:1; case BUTTON_UP: return keys[KEY_UP >> 3] & (1 << (KEY_UP & 7))?0:1; case BUTTON_RIGHT: return keys[KEY_RIGHT >> 3] & (1 << (KEY_RIGHT & 7))?0:1; case BUTTON_DOWN: return keys[KEY_DOWN >> 3] & (1 << (KEY_DOWN & 7))?0:1; case BUTTON_CENTER: return keys[KEY_ENTER >> 3] & (1 << (KEY_ENTER & 7))?0:1; case BUTTON_BACK: return keys[KEY_BACKSPACE >> 3] & (1 << (KEY_BACKSPACE & 7))?0:1; } return 0; }
int SC_LID::open(const char* path) { m_fd = ::open(path, O_RDWR); if (m_fd == -1) { error("LID (1): %s\n", strerror(errno)); return errFailed; } memset(m_eventTypeCaps, 0, sizeof(m_eventTypeCaps)); if (ioctl(m_fd, EVIOCGBIT(0, EV_MAX), m_eventTypeCaps) == -1) { error("LID (2): %s\n", strerror(errno)); return errFailed; } memset(m_keyState, 0, sizeof(m_keyState)); if (ioctl(m_fd, EVIOCGKEY(sizeof(m_keyState)), m_keyState) == -1) { error("LID (3): %s\n", strerror(errno)); return errFailed; } return SC_LIDManager::instance().add(this); }
int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->keyMap.haveKeyLayout()) { Vector<int32_t> scanCodes; device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode, &scanCodes); if (scanCodes.size() != 0) { uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)]; memset(keyState, 0, sizeof(keyState)); if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 0) { for (size_t i = 0; i < scanCodes.size(); i++) { int32_t sc = scanCodes.itemAt(i); if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, keyState)) { return AKEY_STATE_DOWN; } } return AKEY_STATE_UP; } } } return AKEY_STATE_UNKNOWN; }
void uxkb_dev_sleep(struct uterm_input_dev *dev) { /* * While the device is asleep, we don't receive key events. This * means that when we wake up, the keyboard state may be different * (e.g. some key is pressed but we don't know about it). This can * cause various problems, like stuck modifiers: consider if we * miss a release of the left Shift key. When the user presses it * again, xkb_state_update_key() will think there is *another* left * Shift key that was pressed. When the key is released, it's as if * this "second" key was released, but the "first" is still left * pressed. * To handle this, when the device goes to sleep, we save our * current knowledge of the keyboard's press/release state. On wake * up, we compare the states before and after, and just feed * xkb_state_update_key() the deltas. */ memset(dev->key_state_bits, 0, sizeof(dev->key_state_bits)); errno = 0; ioctl(dev->rfd, EVIOCGKEY(sizeof(dev->key_state_bits)), dev->key_state_bits); if (errno) log_warn("failed to save keyboard state (%d): %m", errno); }
int32_t EventHub::getKeyCodeStateLocked(device_t* device, int32_t keyCode) const { Vector<int32_t> scanCodes; device->layoutMap->findScancodes(keyCode, &scanCodes); uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)]; memset(key_bitmask, 0, sizeof(key_bitmask)); if (ioctl(device->fd, EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) { #if 0 for (size_t i=0; i<=KEY_MAX; i++) { LOGI("(Scan code %d: down=%d)", i, test_bit(i, key_bitmask)); } #endif const size_t N = scanCodes.size(); for (size_t i=0; i<N && i<=KEY_MAX; i++) { int32_t sc = scanCodes.itemAt(i); //LOGI("Code %d: down=%d", sc, test_bit(sc, key_bitmask)); if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, key_bitmask)) { return AKEY_STATE_DOWN; } } return AKEY_STATE_UP; } return AKEY_STATE_UNKNOWN; }
int evdev_device_get_keys(struct evdev_device *device, char *keys, size_t size) { memset(keys, 0, size); return ioctl(device->fd, EVIOCGKEY(size), keys); }
int evio_get_joystick_status(evio_handle v, float *abs_x1, float *abs_y1, float *abs_x2, float *abs_y2, int *buttons) { struct input_absinfo absinfo; int xax2, yax2; evio *evp = (evio *) v; int rc=0; memset(&absinfo, 0, sizeof(absinfo)); *abs_x1 = 0; *abs_y1 = 0; *abs_x2 = 0; *abs_y2 = 0; *buttons = 0; if (ioctl(evp->fd, EVIOCGABS(ABS_X), &absinfo) < 0) { return 0; } else { rc |= 1; *abs_x1 = evio_absinfo2float(&absinfo); } if (ioctl(evp->fd, EVIOCGABS(ABS_Y), &absinfo) < 0) { return 0; } else { rc |= 1; *abs_y1 = evio_absinfo2float(&absinfo); } switch (evp->devjoystick) { case EVENTIO_JOYSTICK_LOGIF310: xax2 = ABS_RX; yax2 = ABS_RY; break; case EVENTIO_JOYSTICK_NYKO: xax2 = ABS_Z; yax2 = ABS_RZ; break; default: case EVENTIO_JOYSTICK_STD: xax2 = 0; yax2 = 0; break; } if (xax2 && yax2) { if (ioctl(evp->fd, EVIOCGABS(xax2), &absinfo) < 0) { return 0; } else { rc |= 1; *abs_x2 = evio_absinfo2float(&absinfo); } if (ioctl(evp->fd, EVIOCGABS(yax2), &absinfo) < 0) { return 0; } else { rc |= 1; *abs_y2 = evio_absinfo2float(&absinfo); } } if (ioctl(evp->fd, EVIOCGKEY(sizeof(evp->keystate)), evp->keystate) >= 0) { #if 1 int btmp=0; btmp |= evio_get_button_status(v, BTN_BACK, EVENTIO_BACK); btmp |= evio_get_button_status(v, BTN_TASK, EVENTIO_TASK); btmp |= evio_get_button_status(v, BTN_START, EVENTIO_START); btmp |= evio_get_button_status(v, BTN_A, EVENTIO_GAMEPAD_A); btmp |= evio_get_button_status(v, BTN_B, EVENTIO_GAMEPAD_B); btmp |= evio_get_button_status(v, BTN_X, EVENTIO_GAMEPAD_X); btmp |= evio_get_button_status(v, BTN_Y, EVENTIO_GAMEPAD_Y); btmp |= evio_get_button_status(v, BTN_TL, EVENTIO_TL); btmp |= evio_get_button_status(v, BTN_TR, EVENTIO_TR); btmp |= evio_get_button_status(v, BTN_THUMBL, EVENTIO_THUMBL); btmp |= evio_get_button_status(v, BTN_THUMBR, EVENTIO_THUMBR); #else int i, btmp=0; for (i=0; i<31; i++) { if (EVIO_TESTBIT(BTN_GAMEPAD+i, evp->keybit)) btmp |= (1 << i); } #endif *buttons = btmp; } return rc; }
/* * It so happens that the pointer that gives us the trouble * is the last field in the structure. Since we don't support * custom waveforms in uinput anyway we can just copy the whole * thing (to the compat size) and ignore the pointer. */ memcpy(&ff_up_compat.effect, &ff_up->effect, sizeof(struct ff_effect_compat)); memcpy(&ff_up_compat.old, &ff_up->old, sizeof(struct ff_effect_compat)); if (copy_to_user(buffer, &ff_up_compat, sizeof(struct uinput_ff_upload_compat))) return -EFAULT; } else { if (copy_to_user(buffer, ff_up, sizeof(struct uinput_ff_upload))) return -EFAULT; } return 0; } static int uinput_ff_upload_from_user(const char __user *buffer, struct uinput_ff_upload *ff_up) { if (INPUT_COMPAT_TEST) { struct uinput_ff_upload_compat ff_up_compat; if (copy_from_user(&ff_up_compat, buffer, sizeof(struct uinput_ff_upload_compat))) return -EFAULT; ff_up->request_id = ff_up_compat.request_id; ff_up->retval = ff_up_compat.retval; memcpy(&ff_up->effect, &ff_up_compat.effect, sizeof(struct ff_effect_compat)); memcpy(&ff_up->old, &ff_up_compat.old, sizeof(struct ff_effect_compat)); } else { if (copy_from_user(ff_up, buffer, sizeof(struct uinput_ff_upload))) return -EFAULT; } return 0; } #else static int uinput_ff_upload_to_user(char __user *buffer, const struct uinput_ff_upload *ff_up) { if (copy_to_user(buffer, ff_up, sizeof(struct uinput_ff_upload))) return -EFAULT; return 0; } static int uinput_ff_upload_from_user(const char __user *buffer, struct uinput_ff_upload *ff_up) { if (copy_from_user(ff_up, buffer, sizeof(struct uinput_ff_upload))) return -EFAULT; return 0; } #endif #define uinput_set_bit(_arg, _bit, _max) \ ({ \ int __ret = 0; \ if (udev->state == UIST_CREATED) \ __ret = -EINVAL; \ else if ((_arg) > (_max)) \ __ret = -EINVAL; \ else set_bit((_arg), udev->dev->_bit); \ __ret; \ }) #ifdef CONFIG_FEATURE_PANTECH_MDS_MTC //|| defined(FEATURE_PANTECH_STABILITY) #ifdef CONFIG_COMPAT #define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8) #define BITS_TO_LONGS_COMPAT(x) ((((x) - 1) / BITS_PER_LONG_COMPAT) + 1) #ifdef __BIG_ENDIAN static int bits_to_user(unsigned long *bits, unsigned int maxbit, unsigned int maxlen, void __user *p, int compat) { int len, i; if (compat) { len = BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t); if (len > maxlen) len = maxlen; for (i = 0; i < len / sizeof(compat_long_t); i++) if (copy_to_user((compat_long_t __user *) p + i, (compat_long_t *) bits + i + 1 - ((i % 2) << 1), sizeof(compat_long_t))) return -EFAULT; } else { len = BITS_TO_LONGS(maxbit) * sizeof(long); if (len > maxlen) len = maxlen; if (copy_to_user(p, bits, len)) return -EFAULT; } return len; } #else static int bits_to_user(unsigned long *bits, unsigned int maxbit, unsigned int maxlen, void __user *p, int compat) { int len = compat ? BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t) : BITS_TO_LONGS(maxbit) * sizeof(long); if (len > maxlen) len = maxlen; return copy_to_user(p, bits, len) ? -EFAULT : len; } #endif /* __BIG_ENDIAN */ #else static int bits_to_user(unsigned long *bits, unsigned int maxbit, unsigned int maxlen, void __user *p, int compat) { int len = BITS_TO_LONGS(maxbit) * sizeof(long); if (len > maxlen) len = maxlen; return copy_to_user(p, bits, len) ? -EFAULT : len; } #endif /* CONFIG_COMPAT */ static int str_to_user(const char *str, unsigned int maxlen, void __user *p) { int len; if (!str) return -ENOENT; len = strlen(str) + 1; if (len > maxlen) len = maxlen; return copy_to_user(p, str, len) ? -EFAULT : len; } #define OLD_KEY_MAX 0x1ff static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user *p, int compat_mode) { unsigned long *bits; int len; switch (_IOC_NR(cmd) & EV_MAX) { case 0: bits = dev->evbit; len = EV_MAX; break; case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; case EV_REL: bits = dev->relbit; len = REL_MAX; break; case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; case EV_LED: bits = dev->ledbit; len = LED_MAX; break; case EV_SND: bits = dev->sndbit; len = SND_MAX; break; case EV_FF: bits = dev->ffbit; len = FF_MAX; break; case EV_SW: bits = dev->swbit; len = SW_MAX; break; default: return -EINVAL; } if ((_IOC_NR(cmd) & EV_MAX) == EV_KEY && _IOC_SIZE(cmd) == OLD_KEY_MAX) { len = OLD_KEY_MAX; } return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); } #undef OLD_KEY_MAX #endif/*CONFIG_FEATURE_PANTECH_MDS_MTC || FEATURE_PANTECH_STABILITY*/ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, unsigned long arg, void __user *p) { int retval; struct uinput_device *udev = file->private_data; struct uinput_ff_upload ff_up; struct uinput_ff_erase ff_erase; struct uinput_request *req; char *phys; retval = mutex_lock_interruptible(&udev->mutex); if (retval) return retval; if (!udev->dev) { retval = uinput_allocate_device(udev); if (retval) goto out; } switch (cmd) { case UI_DEV_CREATE: retval = uinput_create_device(udev); break; case UI_DEV_DESTROY: uinput_destroy_device(udev); break; #ifdef CONFIG_FEATURE_PANTECH_MDS_MTC //|| defined(FEATURE_PANTECH_STABILITY) case EVIOCGVERSION: if (udev->state != UIST_CREATED) retval = -ENODEV; else put_user(EV_VERSION, (int __user *)p); break; case EVIOCGID: if (udev->state != UIST_CREATED) retval = -ENODEV; else if (copy_to_user(p, &udev->dev->id, sizeof(struct input_id))) retval = -EFAULT; break; #endif/*CONFIG_FEATURE_PANTECH_MDS_MTC || FEATURE_PANTECH_STABILITY*/ case UI_SET_EVBIT: retval = uinput_set_bit(arg, evbit, EV_MAX); break; case UI_SET_KEYBIT: retval = uinput_set_bit(arg, keybit, KEY_MAX); break; case UI_SET_RELBIT: retval = uinput_set_bit(arg, relbit, REL_MAX); break; case UI_SET_ABSBIT: retval = uinput_set_bit(arg, absbit, ABS_MAX); break; case UI_SET_MSCBIT: retval = uinput_set_bit(arg, mscbit, MSC_MAX); break; case UI_SET_LEDBIT: retval = uinput_set_bit(arg, ledbit, LED_MAX); break; case UI_SET_SNDBIT: retval = uinput_set_bit(arg, sndbit, SND_MAX); break; case UI_SET_FFBIT: retval = uinput_set_bit(arg, ffbit, FF_MAX); break; case UI_SET_SWBIT: retval = uinput_set_bit(arg, swbit, SW_MAX); break; case UI_SET_PROPBIT: retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX); break; case UI_SET_PHYS: if (udev->state == UIST_CREATED) { retval = -EINVAL; goto out; } phys = strndup_user(p, 1024); if (IS_ERR(phys)) { retval = PTR_ERR(phys); goto out; } kfree(udev->dev->phys); udev->dev->phys = phys; break; case UI_BEGIN_FF_UPLOAD: retval = uinput_ff_upload_from_user(p, &ff_up); if (retval) break; req = uinput_request_find(udev, ff_up.request_id); if (!req || req->code != UI_FF_UPLOAD || !req->u.upload.effect) { retval = -EINVAL; break; } ff_up.retval = 0; ff_up.effect = *req->u.upload.effect; if (req->u.upload.old) ff_up.old = *req->u.upload.old; else memset(&ff_up.old, 0, sizeof(struct ff_effect)); retval = uinput_ff_upload_to_user(p, &ff_up); break; case UI_BEGIN_FF_ERASE: if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) { retval = -EFAULT; break; } req = uinput_request_find(udev, ff_erase.request_id); if (!req || req->code != UI_FF_ERASE) { retval = -EINVAL; break; } ff_erase.retval = 0; ff_erase.effect_id = req->u.effect_id; if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) { retval = -EFAULT; break; } break; case UI_END_FF_UPLOAD: retval = uinput_ff_upload_from_user(p, &ff_up); if (retval) break; req = uinput_request_find(udev, ff_up.request_id); if (!req || req->code != UI_FF_UPLOAD || !req->u.upload.effect) { retval = -EINVAL; break; } req->retval = ff_up.retval; uinput_request_done(udev, req); break; case UI_END_FF_ERASE: if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) { retval = -EFAULT; break; } req = uinput_request_find(udev, ff_erase.request_id); if (!req || req->code != UI_FF_ERASE) { retval = -EINVAL; break; } req->retval = ff_erase.retval; uinput_request_done(udev, req); break; default: #ifdef CONFIG_FEATURE_PANTECH_MDS_MTC // || defined(FEATURE_PANTECH_STABILITY) { if (udev->state != UIST_CREATED){ retval = -ENODEV; break; } if (_IOC_DIR(cmd) == _IOC_READ) { if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) handle_eviocgbit(udev->dev, cmd, p, 0); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) bits_to_user(udev->dev->key, KEY_MAX, _IOC_SIZE(cmd), p, 0); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) bits_to_user(udev->dev->led, LED_MAX, _IOC_SIZE(cmd), p, 0); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) bits_to_user(udev->dev->snd, SND_MAX, _IOC_SIZE(cmd), p, 0); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) bits_to_user(udev->dev->sw, SW_MAX, _IOC_SIZE(cmd), p, 0); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) str_to_user(udev->dev->name, _IOC_SIZE(cmd), p); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) str_to_user(udev->dev->phys, _IOC_SIZE(cmd), p); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) str_to_user(udev->dev->uniq, _IOC_SIZE(cmd), p); if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { int t; struct input_absinfo abs; t = _IOC_NR(cmd) & ABS_MAX; abs.value = input_abs_get_val(udev->dev,t); abs.minimum = input_abs_get_min(udev->dev,t); abs.maximum = input_abs_get_max(udev->dev,t); abs.fuzz = input_abs_get_fuzz(udev->dev,t); abs.flat = input_abs_get_flat(udev->dev,t); /* abs.value = udev->dev->abs[t]; abs.minimum = udev->dev->absmin[t]; abs.maximum = udev->dev->absmax[t]; abs.fuzz = udev->dev->absfuzz[t]; abs.flat = udev->dev->absflat[t]; */ if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) retval= -EFAULT; } } } #else retval = -EINVAL; #endif/*CONFIG_FEATURE_PANTECH_MDS_MTC || FEATURE_PANTECH_STABILITY*/ } out: mutex_unlock(&udev->mutex); return retval; }
IOCTL(EVIOCGKEYCODE_V2), #endif IOCTL(EVIOCSKEYCODE), #ifdef EVIOCSKEYCODE_V2 IOCTL(EVIOCSKEYCODE_V2), #endif IOCTL(EVIOCGNAME(0)), IOCTL(EVIOCGPHYS(0)), IOCTL(EVIOCGUNIQ(0)), #ifdef EVIOCGPROP IOCTL(EVIOCGPROP(0)), #endif #ifdef EVIOCGMTSLOTS IOCTL(EVIOCGMTSLOTS(0)), #endif IOCTL(EVIOCGKEY(0)), IOCTL(EVIOCGLED(0)), IOCTL(EVIOCGSND(0)), IOCTL(EVIOCGSW(0)), IOCTL(EVIOCGBIT(0,0)), IOCTL(EVIOCGABS(0)), IOCTL(EVIOCSABS(0)), IOCTL(EVIOCSFF), IOCTL(EVIOCRMFF), IOCTL(EVIOCGEFFECTS), IOCTL(EVIOCGRAB), #ifdef EVIOCSCLOCKID IOCTL(EVIOCSCLOCKID), #endif };
int main(int argc, char *argv[]) { int opt, j, ret; int fd; int options = 0; #define OPT_INFO 1 #define OPT_GRAB 2 #define OPT_LONG 4 #define OPT_INITIAL 0x08 #define OPT_QUIT 0x10 char *device; struct pollfd pollfd = { .events = POLLIN, }; struct input_event evs[16]; /* parse program options */ while ((opt = getopt_long(argc, argv, optstring, long_opts, NULL)) != -1) switch (opt) { case 'V': fprintf(stderr, "%s: %s\n", NAME, VERSION); return 0; case 'i': options |= OPT_INFO; break; case '0': if (options & OPT_INITIAL) options |= OPT_QUIT; options |= OPT_INITIAL; break; case 'g': options |= OPT_GRAB; break; case 'l': options |= OPT_LONG; if (optarg) { double dtime = strtod(optarg, NULL); if (dtime > 0.001) { tlong.tv_sec = lround(floor(dtime)); tlong.tv_usec = lround(dtime * 1e6) % 1000000; } } break; case 'm': if (inputeventloadmap(optarg) < 0) elog(1, errno, "load map from '%s'", optarg); break; default: fprintf(stderr, "%s: option '%c' unrecognised\n", NAME, opt); case '?': fputs(help_msg, stderr); exit(1); } device = argv[optind]; if (!device) { fprintf(stderr, "No device given\n"); fputs(help_msg, stderr); exit(1); } if (options & OPT_LONG) { keytimes = malloc(sizeof(*keytimes) * KEY_CNT); if (!keytimes) elog(1, errno, "malloc keycache\n"); } fd = open(device, O_RDONLY); if (fd < 0) elog(1, errno, "open %s\n", device); /* show info when requested */ if (options & OPT_INFO) { char name[64]; char phys[64]; struct input_id id; if (ioctl(fd, EVIOCGID, &id) < 0) elog(1, errno, "ioctl %s EVIOCGID\n", device); if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) elog(1, errno, "ioctl %s EVIOCGNAME\n", device); if (ioctl(fd, EVIOCGPHYS(sizeof(phys)), phys) < 0) elog(1, errno, "ioctl %s EVIOCGPHYS\n", device); printf("### %s\n", device); printf("name: %s\n", name); printf("phys: %s\n", phys); printf("bus: %u\n", id.bustype); printf("vendor: 0x%04x\n", id.vendor); printf("product: 0x%04x\n", id.product); printf("version: %u\n", id.version); return 0; } if (options & OPT_GRAB) { int value = 1; if (ioctl(fd, EVIOCGRAB, &value) < 0) elog(1, errno, "Grab %s failed\n", device); } if (argv[++optind]) { /* fork child process */ int pp[2]; if (pipe(pp) < 0) elog(1, errno, "pipe() failed\n"); ret = fork(); if (ret < 0) elog(1, errno, "fork() failed\n"); else if (!ret) { dup2(pp[0], STDIN_FILENO); close(pp[0]); close(pp[1]); close(fd); execvp(argv[optind], argv+optind); elog(1, errno, "execvp %s ...", argv[optind]); } dup2(pp[1], STDOUT_FILENO); close(pp[0]); close(pp[1]); } if (options & OPT_INITIAL) { char state[KEY_CNT/8+1]; int j; if (ioctl(fd, EVIOCGKEY(sizeof(state)), state) < 0) elog(1, errno, "ioctl %s EVIOCGKEY\n", device); for (j = 0; j < KEY_CNT; ++j) { if (state[j/8] & (1 << (j % 8))) printf("i %s 1\n", inputeventtostr(EV_KEY, j)); } if (ioctl(fd, EVIOCGSW(sizeof(state)), state) < 0) elog(1, errno, "ioctl %s EVIOCGKEY\n", device); for (j = 0; j < SW_CNT; ++j) { if (state[j/8] & (1 << (j % 8))) printf("i %s 1\n", inputeventtostr(EV_SW, j)); } if (options & OPT_QUIT) return 0; fflush(stdout); } /* prepare main loop */ pollfd.fd = fd; while (1) { libt_flush(); ret = poll(&pollfd, 1, libt_get_waittime()); if (ret < 0) elog(1, errno, "poll"); if (!ret) continue; ret = read(fd, evs, sizeof(evs)); if (ret < 0) elog(1, errno, "read input"); for (j = 0; j < ret/sizeof(*evs); ++j) { if ((options & OPT_LONG) && (evs[j].type == EV_KEY) && !evs[j].value && !libt_timeout_exist(keytimeout, (void *)(long)evs[j].code)) /* long press detection timeout has already passed */ continue; if ((evs[j].type == EV_KEY) && keytimes && (evs[j].code < KEY_CNT)) { /* do longpress detection */ if (evs[j].value == 1) { keytimes[evs[j].code] = evs[j].time; libt_add_timeout(dtlong, keytimeout, (void *)(long)evs[j].code); } else if (!evs[j].value && libt_timeout_exist(keytimeout, (void *)(long)evs[j].code)) /* no long press detected yet */ libt_remove_timeout(keytimeout, (void *)(long)evs[j].code); else /* long press detected, or autorepeat */ continue; } printf("%lu.%06lu %s %i\n", evs[j].time.tv_sec, evs[j].time.tv_usec, inputeventtostr(evs[j].type, evs[j].code), evs[j].value); } fflush(stdout); } return 0; }
static void input_sanitise(const struct ioctl_group *grp, int childno) { unsigned int u, r; pick_random_ioctl(grp, childno); switch (shm->syscall[childno].a2) { case EVIOCGNAME(0): u = rand(); shm->syscall[childno].a2 = EVIOCGNAME(u); break; case EVIOCGPHYS(0): u = rand(); shm->syscall[childno].a2 = EVIOCGPHYS(u); break; case EVIOCGUNIQ(0): u = rand(); shm->syscall[childno].a2 = EVIOCGUNIQ(u); break; #ifdef EVIOCGPROP case EVIOCGPROP(0): u = rand(); shm->syscall[childno].a2 = EVIOCGPROP(u); break; #endif #ifdef EVIOCGMTSLOTS case EVIOCGMTSLOTS(0): u = rand(); shm->syscall[childno].a2 = EVIOCGMTSLOTS(u); break; #endif case EVIOCGKEY(0): u = rand(); shm->syscall[childno].a2 = EVIOCGKEY(u); break; case EVIOCGLED(0): u = rand(); shm->syscall[childno].a2 = EVIOCGLED(u); break; case EVIOCGSND(0): u = rand(); shm->syscall[childno].a2 = EVIOCGSND(u); break; case EVIOCGSW(0): u = rand(); shm->syscall[childno].a2 = EVIOCGSW(u); break; case EVIOCGBIT(0,0): u = rand(); r = rand(); if (u % 10) u %= EV_CNT; if (r % 10) r /= 4; shm->syscall[childno].a2 = EVIOCGBIT(u, r); break; case EVIOCGABS(0): u = rand(); if (u % 10) u %= ABS_CNT; shm->syscall[childno].a2 = EVIOCGABS(u); break; case EVIOCSABS(0): u = rand(); if (u % 10) u %= ABS_CNT; shm->syscall[childno].a2 = EVIOCSABS(u); break; default: break; } }
int main(void) { TEST_NULL_ARG(EVIOCGVERSION); TEST_NULL_ARG(EVIOCGEFFECTS); TEST_NULL_ARG(EVIOCGID); TEST_NULL_ARG(EVIOCGKEYCODE); TEST_NULL_ARG(EVIOCSKEYCODE); TEST_NULL_ARG(EVIOCSFF); # ifdef EVIOCGKEYCODE_V2 TEST_NULL_ARG(EVIOCGKEYCODE_V2); # endif # ifdef EVIOCSKEYCODE_V2 TEST_NULL_ARG(EVIOCSKEYCODE_V2); # endif # ifdef EVIOCGREP TEST_NULL_ARG(EVIOCGREP); # endif # ifdef EVIOCSREP TEST_NULL_ARG(EVIOCSREP); # endif # ifdef EVIOCSCLOCKID TEST_NULL_ARG(EVIOCSCLOCKID); # endif TEST_NULL_ARG(EVIOCGNAME(0)); TEST_NULL_ARG(EVIOCGPHYS(0)); TEST_NULL_ARG(EVIOCGUNIQ(0)); TEST_NULL_ARG(EVIOCGKEY(0)); TEST_NULL_ARG(EVIOCGLED(0)); # ifdef EVIOCGMTSLOTS TEST_NULL_ARG(EVIOCGMTSLOTS(0)); # endif # ifdef EVIOCGPROP TEST_NULL_ARG(EVIOCGPROP(0)); # endif TEST_NULL_ARG(EVIOCGSND(0)); # ifdef EVIOCGSW TEST_NULL_ARG(EVIOCGSW(0)); # endif TEST_NULL_ARG(EVIOCGABS(ABS_X)); TEST_NULL_ARG(EVIOCSABS(ABS_X)); TEST_NULL_ARG(EVIOCGBIT(EV_SYN, 0)); TEST_NULL_ARG(EVIOCGBIT(EV_KEY, 1)); TEST_NULL_ARG(EVIOCGBIT(EV_REL, 2)); TEST_NULL_ARG(EVIOCGBIT(EV_ABS, 3)); TEST_NULL_ARG(EVIOCGBIT(EV_MSC, 4)); # ifdef EV_SW TEST_NULL_ARG(EVIOCGBIT(EV_SW, 5)); # endif TEST_NULL_ARG(EVIOCGBIT(EV_LED, 6)); TEST_NULL_ARG(EVIOCGBIT(EV_SND, 7)); TEST_NULL_ARG(EVIOCGBIT(EV_REP, 8)); TEST_NULL_ARG(EVIOCGBIT(EV_FF, 9)); TEST_NULL_ARG(EVIOCGBIT(EV_PWR, 10)); TEST_NULL_ARG(EVIOCGBIT(EV_FF_STATUS, 11)); ioctl(-1, EVIOCGBIT(EV_MAX, 42), 0); printf("ioctl(-1, EVIOCGBIT(%#x /* EV_??? */, 42), NULL)" " = -1 EBADF (%m)\n", EV_MAX); ioctl(-1, EVIOCRMFF, lmagic); printf("ioctl(-1, EVIOCRMFF, %d) = -1 EBADF (%m)\n", (int) lmagic); ioctl(-1, EVIOCGRAB, lmagic); printf("ioctl(-1, EVIOCGRAB, %lu) = -1 EBADF (%m)\n", lmagic); # ifdef EVIOCREVOKE ioctl(-1, EVIOCREVOKE, lmagic); printf("ioctl(-1, EVIOCREVOKE, %lu) = -1 EBADF (%m)\n", lmagic); # endif const unsigned int size = get_page_size(); void *const page = tail_alloc(size); fill_memory(page, size); int *const val_int = tail_alloc(sizeof(*val_int)); *val_int = magic; # ifdef EVIOCSCLOCKID ioctl(-1, EVIOCSCLOCKID, val_int); printf("ioctl(-1, EVIOCSCLOCKID, [%u]) = -1 EBADF (%m)\n", *val_int); # endif int *pair_int = tail_alloc(sizeof(*pair_int) * 2); pair_int[0] = 0xdeadbeef; pair_int[1] = 0xbadc0ded; # ifdef EVIOSGREP ioctl(-1, EVIOCSREP, pair_int); printf("ioctl(-1, EVIOCSREP, [%u, %u]) = -1 EBADF (%m)\n", pair_int[0], pair_int[1]); # endif pair_int[1] = 1; ioctl(-1, EVIOCSKEYCODE, pair_int); printf("ioctl(-1, EVIOCSKEYCODE, [%u, %s]) = -1 EBADF (%m)\n", pair_int[0], "KEY_ESC"); # ifdef EVIOCSKEYCODE_V2 struct input_keymap_entry *const ike = tail_alloc(sizeof(*ike)); fill_memory(ike, sizeof(*ike)); ike->keycode = 2; ioctl(-1, EVIOCSKEYCODE_V2, ike); printf("ioctl(-1, EVIOCSKEYCODE_V2, {flags=%" PRIu8 ", len=%" PRIu8 ", ", ike->flags, ike->len); # if VERBOSE printf("index=%" PRIu16 ", keycode=%s, scancode=[", ike->index, "KEY_1"); unsigned int i; for (i = 0; i < ARRAY_SIZE(ike->scancode); ++i) { if (i > 0) printf(", "); printf("%" PRIx8, ike->scancode[i]); } printf("]"); # else printf("..."); # endif errno = EBADF; printf("}) = -1 EBADF (%m)\n"); # endif struct ff_effect *const ffe = tail_alloc(sizeof(*ffe)); fill_memory(ffe, sizeof(*ffe)); ffe->type = FF_CONSTANT; ioctl(-1, EVIOCSFF, ffe); print_ffe_common(ffe, "FF_CONSTANT"); # if VERBOSE printf(", constant={level=%hd", ffe->u.constant.level); print_envelope(&ffe->u.constant.envelope); printf("}"); # else printf("..."); # endif errno = EBADF; printf("}) = -1 EBADF (%m)\n"); # if VERBOSE ffe->type = FF_RAMP; ioctl(-1, EVIOCSFF, ffe); print_ffe_common(ffe, "FF_RAMP"); printf(", ramp={start_level=%hd, end_level=%hd", ffe->u.ramp.start_level, ffe->u.ramp.end_level); print_envelope(&ffe->u.ramp.envelope); errno = EBADF; printf("}}) = -1 EBADF (%m)\n"); ffe->type = FF_PERIODIC; ioctl(-1, EVIOCSFF, ffe); print_ffe_common(ffe, "FF_PERIODIC"); printf(", periodic={waveform=%hu, period=%hu, magnitude=%hd" ", offset=%hd, phase=%hu", ffe->u.periodic.waveform, ffe->u.periodic.period, ffe->u.periodic.magnitude, ffe->u.periodic.offset, ffe->u.periodic.phase); print_envelope(&ffe->u.periodic.envelope); printf(", custom_len=%u, custom_data=%p}", ffe->u.periodic.custom_len, ffe->u.periodic.custom_data); errno = EBADF; printf("}) = -1 EBADF (%m)\n"); ffe->type = FF_RUMBLE; ioctl(-1, EVIOCSFF, ffe); print_ffe_common(ffe, "FF_RUMBLE"); printf(", rumble={strong_magnitude=%hu, weak_magnitude=%hu}", ffe->u.rumble.strong_magnitude, ffe->u.rumble.weak_magnitude); errno = EBADF; printf("}) = -1 EBADF (%m)\n"); ffe->type = 0xff; ioctl(-1, EVIOCSFF, ffe); print_ffe_common(ffe, "0xff /* FF_??? */"); errno = EBADF; printf("}) = -1 EBADF (%m)\n"); # endif ioctl(-1, _IOC(_IOC_READ, 0x45, 0x1, 0xff), lmagic); printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n", "_IOC(_IOC_READ, 0x45, 0x1, 0xff)", lmagic); ioctl(-1, _IOC(_IOC_WRITE, 0x45, 0x1, 0xff), lmagic); printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n", "_IOC(_IOC_WRITE, 0x45, 0x1, 0xff)", lmagic); ioctl(-1, _IOC(_IOC_READ|_IOC_WRITE, 0x45, 0xfe, 0xff), lmagic); printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n", "_IOC(_IOC_READ|_IOC_WRITE, 0x45, 0xfe, 0xff)", lmagic); ioctl(-1, _IOC(_IOC_READ|_IOC_WRITE, 0x45, 0, 0), lmagic); printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n", "_IOC(_IOC_READ|_IOC_WRITE, 0x45, 0, 0)", lmagic); puts("+++ exited with 0 +++"); return 0; }
static int print_possible_events(int fd, int print_flags) { uint8_t *bits = NULL; ssize_t bits_size = 0; const char* label; int i, j, k; int res, res2; struct label* bit_labels; const char *bit_label; printf(" events:\n"); for(i = EV_KEY; i <= EV_MAX; i++) { // skip EV_SYN since we cannot query its available codes int count = 0; while(1) { res = ioctl(fd, EVIOCGBIT(i, bits_size), bits); if(res < bits_size) break; bits_size = res + 16; bits = realloc(bits, bits_size * 2); if(bits == NULL) err(1, "failed to allocate buffer of size %d\n", (int)bits_size); } res2 = 0; switch(i) { case EV_KEY: res2 = ioctl(fd, EVIOCGKEY(res), bits + bits_size); label = "KEY"; bit_labels = key_labels; break; case EV_REL: label = "REL"; bit_labels = rel_labels; break; case EV_ABS: label = "ABS"; bit_labels = abs_labels; break; case EV_MSC: label = "MSC"; bit_labels = msc_labels; break; case EV_LED: res2 = ioctl(fd, EVIOCGLED(res), bits + bits_size); label = "LED"; bit_labels = led_labels; break; case EV_SND: res2 = ioctl(fd, EVIOCGSND(res), bits + bits_size); label = "SND"; bit_labels = snd_labels; break; case EV_SW: res2 = ioctl(fd, EVIOCGSW(bits_size), bits + bits_size); label = "SW "; bit_labels = sw_labels; break; case EV_REP: label = "REP"; bit_labels = rep_labels; break; case EV_FF: label = "FF "; bit_labels = ff_labels; break; case EV_PWR: label = "PWR"; bit_labels = NULL; break; case EV_FF_STATUS: label = "FFS"; bit_labels = ff_status_labels; break; default: res2 = 0; label = "???"; bit_labels = NULL; } for(j = 0; j < res; j++) { for(k = 0; k < 8; k++) if(bits[j] & 1 << k) { char down; if(j < res2 && (bits[j + bits_size] & 1 << k)) down = '*'; else down = ' '; if(count == 0) printf(" %s (%04x):", label, i); else if((count & (print_flags & PRINT_LABELS ? 0x3 : 0x7)) == 0 || i == EV_ABS) printf("\n "); if(bit_labels && (print_flags & PRINT_LABELS)) { bit_label = get_label(bit_labels, j * 8 + k); if(bit_label) printf(" %.20s%c%*s", bit_label, down, (int) (20 - strlen(bit_label)), ""); else printf(" %04x%c ", j * 8 + k, down); } else { printf(" %04x%c", j * 8 + k, down); } if(i == EV_ABS) { struct input_absinfo abs; if(ioctl(fd, EVIOCGABS(j * 8 + k), &abs) == 0) { printf(" : value %d, min %d, max %d, fuzz %d, flat %d, resolution %d", abs.value, abs.minimum, abs.maximum, abs.fuzz, abs.flat, abs.resolution); } } count++; } } if(count) printf("\n"); } free(bits); return 0; }
static struct orng_device_info * read_devinfo(struct orng_device_info *devinfo, int with_scancodes, int fd) { int i; char buf[1024]; __u32 sc; __u16 j; int res = 0; __u32 nsc; memset(devinfo, 0, sizeof(*devinfo)); /* device identifier */ if (ioctl(fd, EVIOCGID, &devinfo->id) < 0) { fprintf(stderr, "ioctl(EVIOCGID): %s\n", strerror(errno)); goto err_ioctl; } /* event bits */ if (ioctl(fd, EVIOCGBIT(0, sizeof(devinfo->evbit)), devinfo->evbit) < 0) { fprintf(stderr, "ioctl(EVIOCGBIT(0)): %s\n", strerror(errno)); goto err_ioctl; } /* keys */ if (TEST_ARRAY_BIT(devinfo->evbit, EV_KEY)) { if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(devinfo->keybit)), devinfo->keybit) < 0) { fprintf(stderr, "ioctl(EVIOCGBIT(EV_KEY)): %s\n", strerror(errno)); goto err_ioctl; } /* key state */ if (TEST_ARRAY_BIT(devinfo->evbit, EV_KEY)) { if (ioctl(fd, EVIOCGKEY(sizeof(devinfo->key)), devinfo->key) < 0) { fprintf(stderr, "ioctl(EVIOCGKEY(%zu)): %s\n", sizeof(buf), strerror(errno)); goto err_ioctl; } } /* read mapping between scan codes and key codes */ if (with_scancodes) { nsc = 1ul<<((CHAR_BIT*sizeof(devinfo->keymap[0][0]))-1); for (sc = 0, j = 0; sc < nsc; ++sc) { int map[2] = {sc, 0}; int res = ioctl(fd, EVIOCGKEYCODE, map); if (res < 0) { if (errno != EINVAL) { fprintf(stderr, "ioctl: %s\n", strerror(errno)); goto err_ioctl; } } else { /* save mapping */ devinfo->keymap[j][0] = map[0]; /* scan code */ devinfo->keymap[j][1] = map[1]; /* key code */ ++j; if (j >= sizeof(devinfo->keymap)/sizeof(devinfo->keymap[0])) { break; } } } } } /* relative positioning */ if (TEST_ARRAY_BIT(devinfo->evbit, EV_REL)) { if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(devinfo->relbit)), devinfo->relbit) < 0) { fprintf(stderr, "ioctl(EVIOCGBIT(EV_REL)): %s\n", strerror(errno)); goto err_ioctl; } } /* absolute positioning */ if (TEST_ARRAY_BIT(devinfo->evbit, EV_ABS)) { if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(devinfo->absbit)), devinfo->absbit) < 0) { fprintf(stderr, "ioctl(EVIOCGBIT(EV_ABS)): %s\n", strerror(errno)); goto err_ioctl; } /* limits */ for (i = 0; i <= ABS_MAX; ++i) { if (TEST_ARRAY_BIT(devinfo->absbit, i)) { if (ioctl(fd, EVIOCGABS(i), devinfo->absinfo+i) < 0) { fprintf(stderr, "ioctl(EVIOCGABS(%d)): %s\n", i, strerror(errno)); goto err_ioctl; } } } } /* misc */ if (TEST_ARRAY_BIT(devinfo->evbit, EV_MSC)) { if (ioctl(fd, EVIOCGBIT(EV_MSC, sizeof(devinfo->mscbit)), devinfo->mscbit) < 0) { fprintf(stderr, "ioctl(EVIOCGBIT(EV_MSC)): %s\n", strerror(errno)); goto err_ioctl; } } /* LEDs */ if (TEST_ARRAY_BIT(devinfo->evbit, EV_LED)) { if (ioctl(fd, EVIOCGBIT(EV_LED, sizeof(devinfo->ledbit)), devinfo->ledbit) < 0) { fprintf(stderr, "ioctl(EVIOCGBIT(EV_LED)): %s\n", strerror(errno)); goto err_ioctl; } /* LED state */ if (TEST_ARRAY_BIT(devinfo->evbit, EV_LED)) { if (ioctl(fd, EVIOCGLED(sizeof(devinfo->led)), devinfo->led) < 0) { fprintf(stderr, "ioctl(EVIOCGLED(%zu)): %s\n", sizeof(buf), strerror(errno)); goto err_ioctl; } } } /* sound */ if (TEST_ARRAY_BIT(devinfo->evbit, EV_SND)) { if (ioctl(fd, EVIOCGBIT(EV_SND, sizeof(devinfo->sndbit)), devinfo->sndbit) < 0) { fprintf(stderr, "ioctl(EVIOCGBIT(EV_SND)): %s\n", strerror(errno)); goto err_ioctl; } /* sound state */ if (TEST_ARRAY_BIT(devinfo->evbit, EV_SW)) { if (ioctl(fd, EVIOCGSND(sizeof(devinfo->snd)), devinfo->snd) < 0) { fprintf(stderr, "ioctl(EVIOCGSND(%zu)): %s\n", sizeof(buf), strerror(errno)); goto err_ioctl; } } } /* force feedback */ if (TEST_ARRAY_BIT(devinfo->evbit, EV_FF)) { if (ioctl(fd, EVIOCGBIT(EV_FF, sizeof(devinfo->ffbit)), devinfo->ffbit) < 0) { fprintf(stderr, "ioctl(EVIOCGBIT(EV_FF)): %s\n", strerror(errno)); goto err_ioctl; } } /* switches */ if (TEST_ARRAY_BIT(devinfo->evbit, EV_SW)) { if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(devinfo->swbit)), devinfo->swbit) < 0) { fprintf(stderr, "ioctl(EVIOCGBIT(EV_SW)): %s\n", strerror(errno)); goto err_ioctl; } /* switch state */ if (TEST_ARRAY_BIT(devinfo->evbit, EV_SW)) { if (ioctl(fd, EVIOCGSW(sizeof(devinfo->sw)), devinfo->sw) < 0) { fprintf(stderr, "ioctl(EVIOCGSW(%zu)): %s\n", sizeof(buf), strerror(errno)); goto err_ioctl; } } } /* auto repeat */ if (TEST_ARRAY_BIT(devinfo->evbit, EV_REP)) { if (ioctl(fd, EVIOCGREP, devinfo->rep) < 0) { fprintf(stderr, "ioctl(EVIOCGREP): %s\n", strerror(errno)); goto err_ioctl; } } /* name */ memset(buf, 0, sizeof(buf)); do { res = ioctl(fd, EVIOCGNAME(sizeof(buf)), buf); } while ((res < 0) && (errno == EINTR)); if (res >= 0) { devinfo->name = strndup(buf, sizeof(buf)-1); if (!devinfo->name) { fprintf(stderr, "strdup: %s\n", strerror(errno)); goto err_strdup_name; } } else if (errno != ENOENT) { fprintf(stderr, "ioctl(EVIOCGPHYS(%lu)): %s\n", (unsigned long)sizeof(buf), strerror(errno)); goto err_ioctl; } /* physical location */ memset(buf, 0, sizeof(buf)); do { res = ioctl(fd, EVIOCGPHYS(sizeof(buf)), buf); } while ((res < 0) && (errno == EINTR)); if (res >= 0) { devinfo->phys = strndup(buf, sizeof(buf)-1); if (!devinfo->phys) { fprintf(stderr, "strdup: %s\n", strerror(errno)); goto err_strdup_phys; } } else if (errno != ENOENT) { fprintf(stderr, "ioctl(EVIOCGPHYS(%lu)): %s\n", (unsigned long)sizeof(buf), strerror(errno)); goto err_ioctl; } /* unique identifier */ memset(buf, 0, sizeof(buf)); do { res = ioctl(fd, EVIOCGUNIQ(sizeof(buf)), buf); } while ((res < 0) && (errno == EINTR)); if (res >= 0) { devinfo->uniq = strndup(buf, sizeof(buf)-1); if (!devinfo->uniq) { fprintf(stderr, "strdup: %s\n", strerror(errno)); goto err_strdup_uniq; } } else if (errno != ENOENT) { fprintf(stderr, "ioctl(EVIOCGUNIQ(%lu)): %s\n", (unsigned long)sizeof(buf), strerror(errno)); goto err_ioctl; } return devinfo; err_strdup_uniq: free(devinfo->phys); err_strdup_phys: err_ioctl_gphys: free(devinfo->name); err_strdup_name: err_ioctl: return NULL; }