int main (int argc, char **argv) { int fd, rd, i, j, k; struct input_event ev[64]; int version; unsigned short id[4]; unsigned long bit[EV_MAX][NBITS(KEY_MAX)]; char name[256] = "Unknown"; int abs[5]; if (argc < 2) { printf("Usage: evtest /dev/input/eventX\n"); printf("Where X = input device number\n"); return 1; } if ((fd = open(argv[argc - 1], O_RDONLY)) < 0) { perror("evtest"); return 1; } if (ioctl(fd, EVIOCGVERSION, &version)) { perror("evtest: can't get version"); return 1; } printf("Input driver version is %d.%d.%d\n", version >> 16, (version >> 8) & 0xff, version & 0xff); ioctl(fd, EVIOCGID, id); printf("Input device ID: bus 0x%x vendor 0x%x product 0x%x version 0x%x\n", id[ID_BUS], id[ID_VENDOR], id[ID_PRODUCT], id[ID_VERSION]); ioctl(fd, EVIOCGNAME(sizeof(name)), name); printf("Input device name: \"%s\"\n", name); memset(bit, 0, sizeof(bit)); ioctl(fd, EVIOCGBIT(0, EV_MAX), bit[0]); printf("Supported events:\n"); for (i = 0; i < EV_MAX; i++) if (test_bit(i, bit[0])) { printf(" Event type %d (%s)\n", i, events[i] ? events[i] : "?"); if (!i) continue; ioctl(fd, EVIOCGBIT(i, KEY_MAX), bit[i]); for (j = 0; j < KEY_MAX; j++) if (test_bit(j, bit[i])) { printf(" Event code %d (%s)\n", j, names[i] ? (names[i][j] ? names[i][j] : "?") : "?"); if (i == EV_ABS) { ioctl(fd, EVIOCGABS(j), abs); for (k = 0; k < 5; k++) if ((k < 3) || abs[k]) printf(" %s %6d\n", absval[k], abs[k]); } } } printf("Testing ... (interrupt to exit)\n"); while (1) { rd = read(fd, ev, sizeof(struct input_event) * 64); if (rd < (int) sizeof(struct input_event)) { printf("yyy\n"); perror("\nevtest: error reading"); return 1; } for (i = 0; i < rd / sizeof(struct input_event); i++) if (ev[i].type == EV_SYN) { printf("Event: time %ld.%06ld, -------------- %s ------------\n", ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].code ? "Config Sync" : "Report Sync" ); } else if (ev[i].type == EV_MSC && (ev[i].code == MSC_RAW || ev[i].code == MSC_SCAN)) { printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %02x\n", ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].type, events[ev[i].type] ? events[ev[i].type] : "?", ev[i].code, names[ev[i].type] ? (names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?", ev[i].value); } else { printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %d\n", ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].type, events[ev[i].type] ? events[ev[i].type] : "?", ev[i].code, names[ev[i].type] ? (names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?", ev[i].value); } } }
void Gamepad_detectDevices() { unsigned int numPaths; char ** gamepadPaths; bool duplicate; unsigned int pathIndex, gamepadIndex; struct stat statBuf; struct Gamepad_device * deviceRecord; struct Gamepad_devicePrivate * deviceRecordPrivate; int fd; char name[128]; char * description; int evKeyBits[(KEY_CNT - 1) / sizeof(int) * 8 + 1]; int evAbsBits[(ABS_CNT - 1) / sizeof(int) * 8 + 1]; int bit; struct input_id id; if (!inited) { return; } gamepadPaths = findGamepadPaths(&numPaths); pthread_mutex_lock(&devicesMutex); for (pathIndex = 0; pathIndex < numPaths; pathIndex++) { duplicate = false; for (gamepadIndex = 0; gamepadIndex < numDevices; gamepadIndex++) { if (!strcmp(((struct Gamepad_devicePrivate *) devices[gamepadIndex]->privateData)->path, gamepadPaths[pathIndex])) { duplicate = true; break; } } if (duplicate) { free(gamepadPaths[pathIndex]); continue; } if (!stat(gamepadPaths[pathIndex], &statBuf)) { deviceRecord = (Gamepad_device*)malloc(sizeof(struct Gamepad_device)); deviceRecord->deviceID = nextDeviceID++; deviceRecord->eventDispatcher = EventDispatcher_create(deviceRecord); devices = (Gamepad_device**)realloc(devices, sizeof(struct Gamepad_device *) * (numDevices + 1)); devices[numDevices++] = deviceRecord; fd = open(gamepadPaths[pathIndex], O_RDONLY, 0); deviceRecordPrivate = (Gamepad_devicePrivate*)malloc(sizeof(struct Gamepad_devicePrivate)); deviceRecordPrivate->fd = fd; deviceRecordPrivate->path = gamepadPaths[pathIndex]; memset(deviceRecordPrivate->buttonMap, 0xFF, sizeof(deviceRecordPrivate->buttonMap)); memset(deviceRecordPrivate->axisMap, 0xFF, sizeof(deviceRecordPrivate->axisMap)); deviceRecord->privateData = deviceRecordPrivate; if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) > 0) { description = (char*)malloc(strlen(name + 1)); strcpy(description, name); } else { description = (char*)malloc(strlen(gamepadPaths[pathIndex] + 1)); strcpy(description, gamepadPaths[pathIndex]); } deviceRecord->description = description; if (!ioctl(fd, EVIOCGID, &id)) { deviceRecord->vendorID = id.vendor; deviceRecord->productID = id.product; } else { deviceRecord->vendorID = deviceRecord->productID = 0; } memset(evKeyBits, 0, sizeof(evKeyBits)); memset(evAbsBits, 0, sizeof(evAbsBits)); ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(evKeyBits)), evKeyBits); ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(evAbsBits)), evAbsBits); deviceRecord->numAxes = 0; for (bit = 0; bit < ABS_CNT; bit++) { if (test_bit(bit, evAbsBits)) { if (ioctl(fd, EVIOCGABS(bit), &deviceRecordPrivate->axisInfo[bit]) < 0 || deviceRecordPrivate->axisInfo[bit].minimum == deviceRecordPrivate->axisInfo[bit].maximum) { continue; } deviceRecordPrivate->axisMap[bit] = deviceRecord->numAxes; deviceRecord->numAxes++; } } deviceRecord->numButtons = 0; for (bit = BTN_MISC; bit < KEY_CNT; bit++) { if (test_bit(bit, evKeyBits)) { deviceRecordPrivate->buttonMap[bit - BTN_MISC] = deviceRecord->numButtons; deviceRecord->numButtons++; } } deviceRecord->axisStates = (float*)calloc(sizeof(float), deviceRecord->numAxes); deviceRecord->buttonStates = (bool*)calloc(sizeof(bool), deviceRecord->numButtons); Gamepad_eventDispatcher()->dispatchEvent(Gamepad_eventDispatcher(), GAMEPAD_EVENT_DEVICE_ATTACHED, deviceRecord); pthread_create(&deviceRecordPrivate->thread, NULL, deviceThread, deviceRecord); } } pthread_mutex_unlock(&devicesMutex); }
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; }
static int SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item) { int ret, i; char name[64]; struct input_absinfo abs_info; if (!item->is_touchscreen) return 0; item->touchscreen_data = SDL_calloc(1, sizeof(*item->touchscreen_data)); if (item->touchscreen_data == NULL) return SDL_OutOfMemory(); ret = ioctl(item->fd, EVIOCGNAME(sizeof(name)), name); if (ret < 0) { SDL_free(item->touchscreen_data); return SDL_SetError("Failed to get evdev touchscreen name"); } item->touchscreen_data->name = SDL_strdup(name); if (item->touchscreen_data->name == NULL) { SDL_free(item->touchscreen_data); return SDL_OutOfMemory(); } ret = ioctl(item->fd, EVIOCGABS(ABS_MT_POSITION_X), &abs_info); if (ret < 0) { SDL_free(item->touchscreen_data->name); SDL_free(item->touchscreen_data); return SDL_SetError("Failed to get evdev touchscreen limits"); } item->touchscreen_data->min_x = abs_info.minimum; item->touchscreen_data->max_x = abs_info.maximum; item->touchscreen_data->range_x = abs_info.maximum - abs_info.minimum; ret = ioctl(item->fd, EVIOCGABS(ABS_MT_POSITION_Y), &abs_info); if (ret < 0) { SDL_free(item->touchscreen_data->name); SDL_free(item->touchscreen_data); return SDL_SetError("Failed to get evdev touchscreen limits"); } item->touchscreen_data->min_y = abs_info.minimum; item->touchscreen_data->max_y = abs_info.maximum; item->touchscreen_data->range_y = abs_info.maximum - abs_info.minimum; ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info); if (ret < 0) { SDL_free(item->touchscreen_data->name); SDL_free(item->touchscreen_data); return SDL_SetError("Failed to get evdev touchscreen limits"); } item->touchscreen_data->max_slots = abs_info.maximum + 1; item->touchscreen_data->slots = SDL_calloc( item->touchscreen_data->max_slots, sizeof(*item->touchscreen_data->slots)); if (item->touchscreen_data->slots == NULL) { SDL_free(item->touchscreen_data->name); SDL_free(item->touchscreen_data); return SDL_OutOfMemory(); } for(i = 0; i < item->touchscreen_data->max_slots; i++) { item->touchscreen_data->slots[i].tracking_id = -1; } ret = SDL_AddTouch(item->fd, /* I guess our fd is unique enough */ item->touchscreen_data->name); if (ret < 0) { SDL_free(item->touchscreen_data->slots); SDL_free(item->touchscreen_data->name); SDL_free(item->touchscreen_data); return ret; } return 0; }
static int touchpad_init(struct touchpad_dispatch *touchpad, struct evdev_device *device) { struct motion_filter *accel; unsigned long prop_bits[INPUT_PROP_MAX]; struct input_absinfo absinfo; unsigned long abs_bits[NBITS(ABS_MAX)]; bool has_buttonpad; double width; double height; double diagonal; touchpad->base.interface = &touchpad_interface; touchpad->device = device; /* Detect model */ touchpad->model = get_touchpad_model(device); ioctl(device->fd, EVIOCGPROP(sizeof(prop_bits)), prop_bits); has_buttonpad = TEST_BIT(prop_bits, INPUT_PROP_BUTTONPAD); /* Configure pressure */ ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits); if (TEST_BIT(abs_bits, ABS_PRESSURE)) { ioctl(device->fd, EVIOCGABS(ABS_PRESSURE), &absinfo); configure_touchpad_pressure(touchpad, absinfo.minimum, absinfo.maximum); } /* Configure acceleration factor */ width = abs(device->abs.max_x - device->abs.min_x); height = abs(device->abs.max_y - device->abs.min_y); diagonal = sqrt(width*width + height*height); /* Set default parameters */ touchpad->constant_accel_factor = DEFAULT_CONSTANT_ACCEL_NUMERATOR / diagonal; touchpad->min_accel_factor = DEFAULT_MIN_ACCEL_FACTOR; touchpad->max_accel_factor = DEFAULT_MAX_ACCEL_FACTOR; touchpad->hysteresis.margin_x = diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR; touchpad->hysteresis.margin_y = diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR; touchpad->hysteresis.center_x = 0; touchpad->hysteresis.center_y = 0; /* Configure acceleration profile */ accel = create_pointer_accelator_filter(touchpad_profile); if (accel == NULL) return -1; touchpad->filter = accel; /* Setup initial state */ touchpad->reset = 1; memset(touchpad->motion_history, 0, sizeof touchpad->motion_history); touchpad->motion_index = 0; touchpad->motion_count = 0; touchpad->state = TOUCHPAD_STATE_NONE; touchpad->last_finger_state = 0; touchpad->finger_state = 0; touchpad->fsm.events = NULL; touchpad->fsm.events_count = 0; touchpad->fsm.events_len = 0; touchpad->fsm.state = FSM_IDLE; touchpad->fsm.timer.fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); touchpad->fsm.timer.source = libinput_add_fd(touchpad->device->base.seat->libinput, touchpad->fsm.timer.fd, fsm_timeout_handler, touchpad); if (touchpad->fsm.timer.source == NULL) { close(touchpad->fsm.timer.fd); accel->interface->destroy(accel); return -1; } /* Configure */ touchpad->fsm.enable = !has_buttonpad; return 0; }
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 SDL_bool EV_ConfigJoystick(STJoystick::STJoystickData* joystick, int fd) { int i, t; unsigned long keybit[40]; unsigned long absbit[40]; unsigned long relbit[40]; /* See if this device uses the new unified event API */ if ( (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) && (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) && (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0) ) { joystick->hwdata->is_hid = SDL_TRUE; /* Get the number of buttons, axes, and other thingamajigs */ for ( i=BTN_JOYSTICK; i < KEY_MAX; ++i ) { if ( test_bit(i, keybit) ) { #ifdef DEBUG_INPUT_EVENTS printf("Joystick has button: 0x%x\n", i); #endif joystick->hwdata->key_map[i-BTN_MISC] = joystick->nbuttons; ++joystick->nbuttons; } } for ( i=BTN_MISC; i < BTN_JOYSTICK; ++i ) { if ( test_bit(i, keybit) ) { #ifdef DEBUG_INPUT_EVENTS printf("Joystick has button: 0x%x\n", i); #endif joystick->hwdata->key_map[i-BTN_MISC] = joystick->nbuttons; ++joystick->nbuttons; } } for ( i=0; i<ABS_MAX; ++i ) { /* Skip hats */ if ( i == ABS_HAT0X ) { i = ABS_HAT3Y; continue; } if ( test_bit(i, absbit) ) { int values[5]; if ( ioctl(fd, EVIOCGABS(i), values) < 0 ) continue; #ifdef DEBUG_INPUT_EVENTS printf("Joystick has absolute axis: %x\n", i); printf("Values = { %d, %d, %d, %d, %d }\n", values[0], values[1], values[2], values[3], values[4]); #endif /* DEBUG_INPUT_EVENTS */ joystick->hwdata->abs_map[i] = joystick->naxes; if ( values[1] == values[2] ) { joystick->hwdata->abs_correct[i].used = 0; } else { joystick->hwdata->abs_correct[i].used = 1; joystick->hwdata->abs_correct[i].coef[0] = (values[2] + values[1]) / 2 - values[4]; joystick->hwdata->abs_correct[i].coef[1] = (values[2] + values[1]) / 2 + values[4]; t = ((values[2] - values[1]) / 2 - 2 * values[4]); if ( t != 0 ) { joystick->hwdata->abs_correct[i].coef[2] = (1 << 29) / t; } else { joystick->hwdata->abs_correct[i].coef[2] = 0; } } ++joystick->naxes; } } for ( i=ABS_HAT0X; i <= ABS_HAT3Y; i += 2 ) { if ( test_bit(i, absbit) || test_bit(i+1, absbit) ) { #ifdef DEBUG_INPUT_EVENTS printf("Joystick has hat %d\n",(i-ABS_HAT0X)/2); #endif ++joystick->nhats; } } if ( test_bit(REL_X, relbit) || test_bit(REL_Y, relbit) ) { ++joystick->nballs; } /* Allocate data to keep track of these thingamajigs */ if ( joystick->nhats > 0 ) { if ( allocate_hatdata(joystick) < 0 ) { joystick->nhats = 0; } } if ( joystick->nballs > 0 ) { if ( allocate_balldata(joystick) < 0 ) { joystick->nballs = 0; } } } return(joystick->hwdata->is_hid); }
void Gamepad_detectDevices() { struct input_id id; DIR * dev_input; struct dirent * entity; unsigned int charsConsumed; int num; int fd; int evCapBits[(EV_CNT - 1) / sizeof(int) * 8 + 1]; int evKeyBits[(KEY_CNT - 1) / sizeof(int) * 8 + 1]; int evAbsBits[(ABS_CNT - 1) / sizeof(int) * 8 + 1]; char fileName[PATH_MAX]; bool duplicate; unsigned int gamepadIndex; struct stat statBuf; struct Gamepad_device * deviceRecord; struct Gamepad_devicePrivate * deviceRecordPrivate; char name[128]; char * description; int bit; time_t currentTime; static time_t lastInputStatTime; if (!inited) { return; } pthread_mutex_lock(&devicesMutex); dev_input = opendir("/dev/input"); currentTime = time(NULL); if (dev_input != NULL) { while ((entity = readdir(dev_input)) != NULL) { charsConsumed = 0; if (sscanf(entity->d_name, "event%d%n", &num, &charsConsumed) && charsConsumed == strlen(entity->d_name)) { snprintf(fileName, PATH_MAX, "/dev/input/%s", entity->d_name); if (stat(fileName, &statBuf) || statBuf.st_mtime < lastInputStatTime) { continue; } duplicate = false; for (gamepadIndex = 0; gamepadIndex < numDevices; gamepadIndex++) { if (!strcmp(((struct Gamepad_devicePrivate *) devices[gamepadIndex]->privateData)->path, fileName)) { duplicate = true; break; } } if (duplicate) { continue; } fd = open(fileName, O_RDONLY, 0); memset(evCapBits, 0, sizeof(evCapBits)); memset(evKeyBits, 0, sizeof(evKeyBits)); memset(evAbsBits, 0, sizeof(evAbsBits)); if (ioctl(fd, EVIOCGBIT(0, sizeof(evCapBits)), evCapBits) < 0 || ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(evKeyBits)), evKeyBits) < 0 || ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(evAbsBits)), evAbsBits) < 0) { close(fd); continue; } if (!test_bit(EV_KEY, evCapBits) || !test_bit(EV_ABS, evCapBits) || !test_bit(ABS_X, evAbsBits) || !test_bit(ABS_Y, evAbsBits) || (!test_bit(BTN_TRIGGER, evKeyBits) && !test_bit(BTN_A, evKeyBits) && !test_bit(BTN_1, evKeyBits))) { close(fd); continue; } deviceRecord = malloc(sizeof(struct Gamepad_device)); deviceRecord->deviceID = nextDeviceID++; devices = realloc(devices, sizeof(struct Gamepad_device *) * (numDevices + 1)); devices[numDevices++] = deviceRecord; deviceRecordPrivate = malloc(sizeof(struct Gamepad_devicePrivate)); deviceRecordPrivate->fd = fd; deviceRecordPrivate->path = malloc(strlen(fileName) + 1); strcpy(deviceRecordPrivate->path, fileName); memset(deviceRecordPrivate->buttonMap, 0xFF, sizeof(deviceRecordPrivate->buttonMap)); memset(deviceRecordPrivate->axisMap, 0xFF, sizeof(deviceRecordPrivate->axisMap)); deviceRecord->privateData = deviceRecordPrivate; if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) > 0) { description = malloc(strlen(name) + 1); strcpy(description, name); } else { description = malloc(strlen(fileName) + 1); strcpy(description, fileName); } deviceRecord->description = description; if (!ioctl(fd, EVIOCGID, &id)) { deviceRecord->vendorID = id.vendor; deviceRecord->productID = id.product; } else { deviceRecord->vendorID = deviceRecord->productID = 0; } memset(evKeyBits, 0, sizeof(evKeyBits)); memset(evAbsBits, 0, sizeof(evAbsBits)); ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(evKeyBits)), evKeyBits); ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(evAbsBits)), evAbsBits); deviceRecord->numAxes = 0; for (bit = 0; bit < ABS_CNT; bit++) { if (test_bit(bit, evAbsBits)) { if (ioctl(fd, EVIOCGABS(bit), &deviceRecordPrivate->axisInfo[bit]) < 0 || deviceRecordPrivate->axisInfo[bit].minimum == deviceRecordPrivate->axisInfo[bit].maximum) { continue; } deviceRecordPrivate->axisMap[bit] = deviceRecord->numAxes; deviceRecord->numAxes++; } } deviceRecord->numButtons = 0; for (bit = BTN_MISC; bit < KEY_CNT; bit++) { if (test_bit(bit, evKeyBits)) { deviceRecordPrivate->buttonMap[bit - BTN_MISC] = deviceRecord->numButtons; deviceRecord->numButtons++; } } deviceRecord->axisStates = calloc(sizeof(float), deviceRecord->numAxes); deviceRecord->buttonStates = calloc(sizeof(bool), deviceRecord->numButtons); if (Gamepad_deviceAttachCallback != NULL) { Gamepad_deviceAttachCallback(deviceRecord, Gamepad_deviceAttachContext); } pthread_create(&deviceRecordPrivate->thread, NULL, deviceThread, deviceRecord); } } closedir(dev_input); } lastInputStatTime = currentTime; pthread_mutex_unlock(&devicesMutex); }
static int vk_init(struct ev *e) { char vk_path[PATH_MAX] = "/sys/board_properties/virtualkeys."; char vks[2048], *ts; ssize_t len; int vk_fd; int i; e->vk_count = 0; len = strlen(vk_path); len = ioctl(e->fd->fd, EVIOCGNAME(sizeof(vk_path) - len), vk_path + len); if (len <= 0) return -1; vk_fd = open(vk_path, O_RDONLY); if (vk_fd < 0) return -1; len = read(vk_fd, vks, sizeof(vks)-1); close(vk_fd); if (len <= 0) return -1; vks[len] = '\0'; /* Parse a line like: keytype:keycode:centerx:centery:width:height:keytype2:keycode2:centerx2:... */ for (ts = vks, e->vk_count = 1; *ts; ++ts) { if (*ts == ':') ++e->vk_count; } if (e->vk_count % 6) { LOGW("minui: %s is %d %% 6\n", vk_path, e->vk_count % 6); } e->vk_count /= 6; if (e->vk_count <= 0) return -1; e->sent = 0; e->mt_idx = 0; ioctl(e->fd->fd, EVIOCGABS(ABS_X), &e->p.xi); ioctl(e->fd->fd, EVIOCGABS(ABS_Y), &e->p.yi); e->p.pressed = 0; ioctl(e->fd->fd, EVIOCGABS(ABS_MT_POSITION_X), &e->mt_p.xi); ioctl(e->fd->fd, EVIOCGABS(ABS_MT_POSITION_Y), &e->mt_p.yi); e->mt_p.pressed = 0; e->vks = malloc(sizeof(*e->vks) * e->vk_count); for (i = 0; i < e->vk_count; ++i) { char *token[6]; int j; for (j = 0; j < 6; ++j) { token[j] = vk_strtok_r((i||j)?NULL:vks, ":", &ts); } if (strcmp(token[0], "0x01") != 0) { /* Java does string compare, so we do too. */ LOGW("minui: %s: ignoring unknown virtual key type %s\n", vk_path, token[0]); continue; } e->vks[i].scancode = strtol(token[1], NULL, 0); e->vks[i].centerx = strtol(token[2], NULL, 0); e->vks[i].centery = strtol(token[3], NULL, 0); e->vks[i].width = strtol(token[4], NULL, 0); e->vks[i].height = strtol(token[5], NULL, 0); } return 0; }
#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 }; static const char *const input_devs[] = { "input", }; static void input_sanitise(const struct ioctl_group *grp, int childno)
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; } }
/* Init Event Device Properties */ static byte aipInitEventDev(AIP_EVP e){ /* Variables */ char vk_path[PATH_MAX] = "/sys/board_properties/virtualkeys."; char vks[2048], *ts = NULL; ssize_t len; int vk_fd; int i; e->vkn = 0; len = strlen(vk_path); len = ioctl(_aip->fds[e->fd_id].fd, EVIOCGNAME(sizeof(e->device_name)), e->device_name); if (len <= 0){ return 0; } /* Blacklist these "input" devices */ if (strcmp(e->device_name, "bma250") == 0){ e->ignored = 1; } /* virtualkeys.{device_name} */ strcat(vk_path, e->device_name); /* Some devices split the keys from the touchscreen */ e->vkn = 0; vk_fd = open(vk_path, O_RDONLY); if (vk_fd >= 0){ /* Read Contents */ len = read(vk_fd, vks, sizeof(vks)-1); close(vk_fd); /* Return False on Failed */ if (len<=0){ return 0; } /* Add string break */ vks[len] = '\0'; /* Parse a line like: keytype:keycode:centerx:centery:width:height:keytype2:keycode2:centerx2:... */ for (ts=vks, e->vkn=1; *ts; ++ts) { if (*ts == ':'){ e->vkn++; } } e->vkn /= 6; if (e->vkn <= 0){ return 0; } e->down = 0; } /* IOCTL ABS DEVICE */ ioctl(_aip->fds[e->fd_id].fd, EVIOCGABS(AIP_ABS_X), &e->p.xi); ioctl(_aip->fds[e->fd_id].fd, EVIOCGABS(AIP_ABS_Y), &e->p.yi); ioctl(_aip->fds[e->fd_id].fd, EVIOCGABS(AIP_ABS_MT_POSITION_X), &e->mt_p.xi); ioctl(_aip->fds[e->fd_id].fd, EVIOCGABS(AIP_ABS_MT_POSITION_Y), &e->mt_p.yi); e->p.synced = 0; e->mt_p.synced = 0; /* LOGS */ printf("\nDEVICE NAME: %s - %s\n", e->device_name, vk_path); printf("EV ST: minX: %d maxX: %d minY: %d maxY: %d\n", e->p.xi.minimum, e->p.xi.maximum, e->p.yi.minimum, e->p.yi.maximum); printf("EV MT: minX: %d maxX: %d minY: %d maxY: %d\n", e->mt_p.xi.minimum, e->mt_p.xi.maximum, e->mt_p.yi.minimum, e->mt_p.yi.maximum); /* Allocate Virtualkeys Count */ e->vks = malloc(sizeof(AIP_VK) * e->vkn); for (i=0; i<e->vkn; ++i) { char * token[6]; int j; for (j=0; j<6; ++j) { token[j] = aipStrTokR((i||j)?NULL:vks, ":", &ts); } if (strcmp(token[0],"0x01") != 0) { continue; } /* Dump It */ e->vks[i].scan = strtol(token[1], NULL, 0); e->vks[i].x = strtol(token[2], NULL, 0); e->vks[i].y = strtol(token[3], NULL, 0); e->vks[i].w = strtol(token[4], NULL, 0); e->vks[i].h = strtol(token[5], NULL, 0); } /* OK */ return 1; }
void lightgun_event_abs_init(void) { int i; for (i = 0; i < GUN_MAX; i++) { char name[256] = "Unknown"; uint8_t abs_bitmask[ABS_MAX/8 + 1]; struct input_absinfo abs_features; if (!lg_devices[i].device) continue; if ((lg_devices[i].fd = open(lg_devices[i].device, O_RDONLY)) < 0) { fprintf(stderr_file, "Lightgun%d: %s[open]: %s", i + 1, lg_devices[i].device, strerror(errno)); continue; } if (ioctl(lg_devices[i].fd, EVIOCGNAME(sizeof(name)), name) < 0) { fprintf(stderr_file, "Lightgun%d: %s[ioctl/EVIOCGNAME]: %s\n", i + 1, lg_devices[i].device, strerror(errno)); lg_devices[i].device = NULL; continue; } memset(abs_bitmask, 0, sizeof(abs_bitmask)); if (ioctl(lg_devices[i].fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) < 0) { fprintf(stderr_file, "Lightgun%d: %s[ioctl/EVIOCGNAME]: %s\n", i + 1, lg_devices[i].device, strerror(errno)); lg_devices[i].device = NULL; continue; } /* Make sure we have an X and Y axis. Not much good * without it. */ if (!test_bit(ABS_X, abs_bitmask) || !test_bit(ABS_Y, abs_bitmask)) { fprintf(stderr_file, "Lightgun%d: %s: Does not contain both X and Y axis, " "ignoring\n", i + 1, lg_devices[i].device); lg_devices[i].device = NULL; continue; } if (ioctl(lg_devices[i].fd, EVIOCGABS(ABS_X), &abs_features)) { fprintf(stderr_file, "Lightgun%d: %s[ioctl/EVIOCGABS(ABX_X)]: %s\n", i + 1, lg_devices[i].device, strerror(errno)); lg_devices[i].device = NULL; continue; } lg_devices[i].min[LG_X_AXIS] = abs_features.minimum; lg_devices[i].range[LG_X_AXIS] = abs_features.maximum - abs_features.minimum; if (ioctl(lg_devices[i].fd, EVIOCGABS(ABS_Y), &abs_features)) { fprintf(stderr_file, "Lightgun%d: %s[ioctl/EVIOCGABS(ABX_Y)]: %s\n", i + 1, lg_devices[i].device, strerror(errno)); lg_devices[i].device = NULL; continue; } lg_devices[i].min[LG_Y_AXIS] = abs_features.minimum; lg_devices[i].range[LG_Y_AXIS] = abs_features.maximum - abs_features.minimum; fprintf(stderr_file, "Lightgun%d: %s\n", i + 1, name); fprintf(stderr_file, " X axis: min[%d] range[%d]\n", lg_devices[i].min[LG_X_AXIS], lg_devices[i].range[LG_X_AXIS]); fprintf(stderr_file, " Y axis: min[%d] range[%d]\n", lg_devices[i].min[LG_Y_AXIS], lg_devices[i].range[LG_Y_AXIS]); } }
static int evdev_handle_device(struct evdev_device *device) { struct input_absinfo absinfo; unsigned long ev_bits[NBITS(EV_MAX)]; unsigned long abs_bits[NBITS(ABS_MAX)]; unsigned long rel_bits[NBITS(REL_MAX)]; unsigned long key_bits[NBITS(KEY_MAX)]; int has_key, has_abs; unsigned int i; has_key = 0; has_abs = 0; device->caps = 0; ioctl(device->fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits); if (TEST_BIT(ev_bits, EV_ABS)) { has_abs = 1; ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits); if (TEST_BIT(abs_bits, ABS_X)) { ioctl(device->fd, EVIOCGABS(ABS_X), &absinfo); device->abs.min_x = absinfo.minimum; device->abs.max_x = absinfo.maximum; device->caps |= EVDEV_MOTION_ABS; } if (TEST_BIT(abs_bits, ABS_Y)) { ioctl(device->fd, EVIOCGABS(ABS_Y), &absinfo); device->abs.min_y = absinfo.minimum; device->abs.max_y = absinfo.maximum; device->caps |= EVDEV_MOTION_ABS; } if (TEST_BIT(abs_bits, ABS_MT_SLOT)) { ioctl(device->fd, EVIOCGABS(ABS_MT_POSITION_X), &absinfo); device->abs.min_x = absinfo.minimum; device->abs.max_x = absinfo.maximum; ioctl(device->fd, EVIOCGABS(ABS_MT_POSITION_Y), &absinfo); device->abs.min_y = absinfo.minimum; device->abs.max_y = absinfo.maximum; device->is_mt = 1; device->mt.slot = 0; device->caps |= EVDEV_TOUCH; } } if (TEST_BIT(ev_bits, EV_REL)) { ioctl(device->fd, EVIOCGBIT(EV_REL, sizeof(rel_bits)), rel_bits); if (TEST_BIT(rel_bits, REL_X) || TEST_BIT(rel_bits, REL_Y)) device->caps |= EVDEV_MOTION_REL; } if (TEST_BIT(ev_bits, EV_KEY)) { has_key = 1; ioctl(device->fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), key_bits); if (TEST_BIT(key_bits, BTN_TOOL_FINGER) && !TEST_BIT(key_bits, BTN_TOOL_PEN) && has_abs) device->dispatch = evdev_touchpad_create(device); for (i = KEY_ESC; i < KEY_MAX; i++) { if (i >= BTN_MISC && i < KEY_OK) continue; if (TEST_BIT(key_bits, i)) { device->caps |= EVDEV_KEYBOARD; break; } } for (i = BTN_MISC; i < KEY_OK; i++) { if (TEST_BIT(key_bits, i)) { device->caps |= EVDEV_BUTTON; break; } } } if (TEST_BIT(ev_bits, EV_LED)) { device->caps |= EVDEV_KEYBOARD; } /* This rule tries to catch accelerometer devices and opt out. We may * want to adjust the protocol later adding a proper event for dealing * with accelerometers and implement here accordingly */ if (has_abs && !has_key && !device->is_mt) { weston_log("input device %s, %s " "ignored: unsupported device type\n", device->devname, device->devnode); return 0; } return 1; }
HIDDevice::HIDDevice(VRDevice::Factory* sFactory,VRDeviceManager* sDeviceManager,Misc::ConfigurationFile& configFile) :VRDevice(sFactory,sDeviceManager,configFile), deviceFd(-1), keyMap(0), absAxisMap(0),relAxisMap(0),axisConverters(0), reportEvents(false), buttonStates(0),valuatorStates(0) { /* First option: Open device by explicit event device file name: */ if(deviceFd<0) { std::string deviceFileName=configFile.retrieveString("./deviceFileName",""); if(deviceFileName!="") { #ifdef VERBOSE printf("HIDDevice: Opening device %s\n",deviceFileName.c_str()); fflush(stdout); #endif deviceFd=open(deviceFileName.c_str(),O_RDONLY); if(deviceFd<0) Misc::throwStdErr("HIDDevice: Unable to open device file \"%s\"",deviceFileName.c_str()); } } /* Second option: Open device by vendor ID / product ID: */ if(deviceFd<0) { std::string deviceVendorProductId=configFile.retrieveString("./deviceVendorProductId",""); if(deviceVendorProductId!="") { /* Split ID string into vendor ID / product ID: */ char* colonPtr; int vendorId=strtol(deviceVendorProductId.c_str(),&colonPtr,16); char* endPtr; int productId=strtol(colonPtr+1,&endPtr,16); if(*colonPtr!=':'||*endPtr!='\0'||vendorId<0||productId<0) Misc::throwStdErr("HIDDevice: Malformed vendorId:productId string \"%s\"",deviceVendorProductId.c_str()); #ifdef VERBOSE printf("HIDDevice: Searching device %04x:%04x\n",vendorId,productId); fflush(stdout); #endif deviceFd=findDevice(vendorId,productId); if(deviceFd<0) Misc::throwStdErr("HIDDevice: No device with vendorId:productId %04x:%04x found",vendorId,productId); } } /* Third option: Open device by device name: */ if(deviceFd<0) { std::string deviceName=configFile.retrieveString("./deviceName",""); if(deviceName!="") { #ifdef VERBOSE printf("HIDDevice: Searching device %s\n",deviceName.c_str()); fflush(stdout); #endif deviceFd=findDevice(deviceName.c_str()); if(deviceFd<0) Misc::throwStdErr("HIDDevice: No device with name \"%s\" found",deviceName.c_str()); } } /* Bail out if no device was found: */ if(deviceFd<0) Misc::throwStdErr("HIDDevice: No device specified"); /* Set number of trackers on device: */ setNumTrackers(0,configFile); /* Query all feature types of the device: */ unsigned char featureTypeBits[EV_MAX/8+1]; memset(featureTypeBits,0,EV_MAX/8+1); if(ioctl(deviceFd,EVIOCGBIT(0,sizeof(featureTypeBits)),featureTypeBits)<0) Misc::throwStdErr("HIDDevice: Unable to query device feature types"); /* Query the number of keys on the device: */ if(featureTypeBits[EV_KEY/8]&(1<<(EV_KEY%8))) { #ifdef VERBOSE printf("HIDDevice: Initializing buttons...\n"); fflush(stdout); #endif /* Query key features: */ unsigned char keyBits[KEY_MAX/8+1]; memset(keyBits,0,KEY_MAX/8+1); if(ioctl(deviceFd,EVIOCGBIT(EV_KEY,sizeof(keyBits)),keyBits)<0) Misc::throwStdErr("HIDDevice: Unable to query device key features"); /* Initialize the key translation array: */ keyMap=new int[KEY_MAX+1]; int numKeys=0; for(int i=0;i<=KEY_MAX;++i) { if(keyBits[i/8]&(1<<(i%8))) { keyMap[i]=numKeys; ++numKeys; } else keyMap[i]=-1; } /* Set number of buttons on device: */ #ifdef VERBOSE printf("HIDDevice: %d buttons found\n",numKeys); fflush(stdout); #endif setNumButtons(numKeys,configFile); } else setNumButtons(0,configFile); /* Count the number of absolute and relative axes: */ int numAxes=0; /* Query the number of absolute axes on the device: */ if(featureTypeBits[EV_ABS/8]&(1<<(EV_ABS%8))) { #ifdef VERBOSE printf("HIDDevice: Initializing absolute axes...\n"); fflush(stdout); #endif /* Query absolute axis features: */ unsigned char absAxisBits[ABS_MAX/8+1]; memset(absAxisBits,0,ABS_MAX/8+1); if(ioctl(deviceFd,EVIOCGBIT(EV_ABS,sizeof(absAxisBits)),absAxisBits)<0) Misc::throwStdErr("HIDDevice: Unable to query device absolute axis features"); /* Initialize the axis translation array: */ absAxisMap=new int[ABS_MAX+1]; int numAbsAxes=0; for(int i=0;i<=ABS_MAX;++i) { if(absAxisBits[i/8]&(1<<(i%8))) { absAxisMap[i]=numAxes; ++numAxes; ++numAbsAxes; } else absAxisMap[i]=-1; } #ifdef VERBOSE printf("HIDDevice: %d absolute axes found\n",numAbsAxes); fflush(stdout); #endif } /* Query the number of relative axes on the device: */ if(featureTypeBits[EV_REL/8]&(1<<(EV_REL%8))) { #ifdef VERBOSE printf("HIDDevice: Initializing relative axes...\n"); fflush(stdout); #endif /* Query relative axis features: */ unsigned char relAxisBits[REL_MAX/8+1]; memset(relAxisBits,0,REL_MAX/8+1); if(ioctl(deviceFd,EVIOCGBIT(EV_REL,sizeof(relAxisBits)),relAxisBits)<0) Misc::throwStdErr("HIDDevice: Unable to query device relative axis features"); /* Initialize the axis translation array: */ relAxisMap=new int[REL_MAX+1]; int numRelAxes=0; for(int i=0;i<=REL_MAX;++i) { if(relAxisBits[i/8]&(1<<(i%8))) { relAxisMap[i]=numAxes; ++numAxes; ++numRelAxes; } else relAxisMap[i]=-1; } #ifdef VERBOSE printf("HIDDevice: %d relative axes found\n",numRelAxes); fflush(stdout); #endif } /* Set number of valuators on device: */ setNumValuators(numAxes,configFile); /* Initialize axis converters: */ axisConverters=new AxisConverter[numAxes]; if(absAxisMap!=0) { /* Initialize absolute axis converters: */ #ifdef VERBOSE printf("HIDDevice: Initializing absolute axis converters\n"); fflush(stdout); #endif for(int i=0;i<=ABS_MAX;++i) if(absAxisMap[i]>=0) { /* Query configuration of this axis: */ input_absinfo absAxisConf; if(ioctl(deviceFd,EVIOCGABS(i),&absAxisConf)<0) Misc::throwStdErr("HIDDevice: Unable to query device absolute axis configuration"); #ifdef VERBOSE printf("Axis %2d: min %d, max %d, fuzz %d, flat %d\n",absAxisMap[i],absAxisConf.minimum,absAxisConf.maximum,absAxisConf.fuzz,absAxisConf.flat); fflush(stdout); #endif /* Initialize converter with queried values: */ AxisConverter& converter=axisConverters[absAxisMap[i]]; float mid=Math::mid(absAxisConf.minimum,absAxisConf.maximum); converter=AxisConverter(absAxisConf.minimum,mid-absAxisConf.flat,mid+absAxisConf.flat,absAxisConf.maximum); /* Override axis settings from configuration file: */ char axisSettingsTag[20]; snprintf(axisSettingsTag,sizeof(axisSettingsTag),"axis%dSettings",absAxisMap[i]); converter=configFile.retrieveValue<AxisConverter>(axisSettingsTag,converter); #ifdef VERBOSE printf("Axis %2d: %s\n",absAxisMap[i],Misc::ValueCoder<AxisConverter>::encode(converter).c_str()); fflush(stdout); #endif } } if(relAxisMap!=0) { /* Initialize relative axis converters: */ #ifdef VERBOSE printf("HIDDevice: Initializing relative axis converters\n"); fflush(stdout); #endif for(int i=0;i<=REL_MAX;++i) if(relAxisMap[i]>=0) { /* Initialize converter with default values: */ AxisConverter& converter=axisConverters[relAxisMap[i]]; converter=AxisConverter(-1.0f,1.0f); /* Override axis settings from configuration file: */ char axisSettingsTag[20]; snprintf(axisSettingsTag,sizeof(axisSettingsTag),"axis%dSettings",relAxisMap[i]); converter=configFile.retrieveValue<AxisConverter>(axisSettingsTag,converter); #ifdef VERBOSE printf("Axis %2d: %s\n",relAxisMap[i],Misc::ValueCoder<AxisConverter>::encode(converter).c_str()); fflush(stdout); #endif } } #if 0 /* Initialize gain arrays: */ valuatorGains=new float[getNumValuators()]; for(int i=0;i<getNumValuators();++i) { char valuatorGainTag[40]; snprintf(valuatorGainTag,sizeof(valuatorGainTag),"./valuatorGain%d",i); valuatorGains[i]=configFile.retrieveValue<float>(valuatorGainTag,1.0f); } #endif /* Initialize state arrays: */ buttonStates=new bool[getNumButtons()]; for(int i=0;i<getNumButtons();++i) buttonStates[i]=false; valuatorStates=new float[getNumValuators()]; for(int i=0;i<getNumValuators();++i) valuatorStates[i]=0.0f; /* Start device thread (HID device cannot be disabled): */ startDeviceThread(); }
int init_hid_device(char* device_name) { int cnt; unsigned long buttons,axes; unsigned long key_bits[32],abs_bits[32],led_bits[32]; // unsigned long ff_bits[32]; int valbuf[16]; char name[MAX_NAME_LENGTH] = "Unknown"; stick_button_count = 0; stick_axis_count = 0; /* Detect device mode, event interface or joystick */ if (strstr( device_name, "event" ) == 0 ) { dbgprintf(stderr," Using Joystick interface\n"); event_mode = STICK_MODE_JOYSTICK; } else { dbgprintf(stderr," Using Event interface\n"); event_mode = STICK_MODE_EVENT; } /* Open event device read only (with write permission for ff) */ stick_device_handle = open(device_name,O_RDONLY|O_NONBLOCK); if (stick_device_handle<0) { dbgprintf(stderr,"ERROR: can not open %s (%s) [%s:%d]\n", device_name,strerror(errno),__FILE__,__LINE__); return(1); } /* LED testing */ // led_test( ); /* Which buttons has the device? */ memset(key_bits,0,32*sizeof(unsigned long)); memset(led_bits,0,32*sizeof(unsigned long)); if (event_mode == STICK_MODE_EVENT ) { if (ioctl(stick_device_handle,EVIOCGBIT(EV_KEY,32*sizeof(unsigned long)),key_bits)<0) { dbgprintf(stderr,"ERROR: can not get key bits (%s) [%s:%d]\n", strerror(errno),__FILE__,__LINE__); return(1); } //read LED count if (ioctl(stick_device_handle,EVIOCGLED(32*sizeof(led_bits)),led_bits)<0) { dbgprintf(stderr,"ERROR: can not get LED bits (%s) [%s:%d]\n", strerror(errno),__FILE__,__LINE__); return(1); } dbgprintf(stderr,"LEDs: %X",*led_bits); } else { if (ioctl(stick_device_handle,JSIOCGBUTTONS,&buttons)<0) { dbgprintf(stderr,"ERROR: can not get key bits (%s) [%s:%d]\n", strerror(errno),__FILE__,__LINE__); return(1); } } /* Store buttons */ if (stick_init_param.button_count > 0) { for (cnt = 0; cnt < MIN(stick_init_param.button_count,BUTTON_COUNT); cnt++) { if (!TEST_BIT(stick_init_param.button_code[cnt], key_bits)) { dbgprintf(stderr,"ERROR: no suitable custom button %d found [%s:%d]\n",cnt,__FILE__,__LINE__); return 1; } } stick_button_count = stick_init_param.button_count; memcpy(button_code,stick_init_param.button_code,BUTTON_COUNT*sizeof(int)); } else { if (event_mode == STICK_MODE_EVENT) { for (cnt = MIN_BUTTON_CODE; cnt < MAX_BUTTON_CODE; cnt++) { if (TEST_BIT(cnt, key_bits)) { button_code[stick_button_count++] = cnt; dbgprintf(stderr,"Available button: %d (0x%x)\n",cnt,cnt); } if (stick_button_count == BUTTON_COUNT) break; } } else { for (cnt = 0; cnt < buttons; cnt++) { button_code[stick_button_count++] = cnt; dbgprintf(stderr,"Available button: %d (0x%x)\n",cnt,cnt); if (stick_button_count == BUTTON_COUNT) break; } } if (stick_button_count == 0) { dbgprintf(stderr,"ERROR: no suitable buttons found [%s:%d]\n",__FILE__,__LINE__); } } /* Which axis has the device? */ memset(abs_bits,0,32*sizeof(unsigned long)); if (event_mode == STICK_MODE_EVENT ) { if (ioctl(stick_device_handle,EVIOCGBIT(EV_ABS,32*sizeof(unsigned long)),abs_bits)<0) { dbgprintf(stderr,"ERROR: can not get abs bits (%s) [%s:%d]\n", strerror(errno),__FILE__,__LINE__); return(1); } } else { if (ioctl(stick_device_handle,JSIOCGAXES,&axes)<0) { dbgprintf(stderr,"ERROR: can not get abs bits (%s) [%s:%d]\n", strerror(errno),__FILE__,__LINE__); return(1); } } /* Store axis */ if (stick_init_param.axis_count > 0) { for (cnt = 0; cnt < MIN(stick_init_param.axis_count,AXIS_COUNT); cnt++) { if (!TEST_BIT(stick_init_param.axis_code[cnt], abs_bits)) { dbgprintf(stderr,"ERROR: no suitable custom axis %d found [%s:%d]\n",cnt,__FILE__,__LINE__); return 1; } } stick_axis_count = stick_init_param.axis_count; memcpy(axis_code,stick_init_param.axis_code,AXIS_COUNT*sizeof(int)); } else { if(event_mode == STICK_MODE_EVENT) { for (cnt = MIN_ABS_CODE; cnt < MAX_ABS_CODE; cnt++) { if (TEST_BIT(cnt, abs_bits)) { axis_code[stick_axis_count++] = cnt; dbgprintf(stderr,"Available axis: %d (0x%x)\n",cnt,cnt); } if (stick_axis_count == AXIS_COUNT) break; } } else { for (cnt = 0; cnt < axes; cnt++) { axis_code[stick_axis_count++] = cnt; dbgprintf(stderr,"Available axis: %d (0x%x)\n",cnt,cnt); if (stick_axis_count == AXIS_COUNT) break; } } // at least 2 axis are needed in auto detection if (stick_axis_count < 2) { dbgprintf(stderr,"ERROR: no suitable axis found [%s:%d]\n",__FILE__,__LINE__); return(1); } } /* Axis param */ for (cnt = 0; cnt < stick_axis_count; cnt++) { if (event_mode == STICK_MODE_EVENT ) { /* get axis value range */ if (ioctl(stick_device_handle,EVIOCGABS(axis_code[cnt]),valbuf)<0) { dbgprintf(stderr,"ERROR: can not get axis %d value range (%s) [%s:%d]\n", cnt,strerror(errno),__FILE__,__LINE__); return(1); } axis_min[cnt]=valbuf[1]; axis_max[cnt]=valbuf[2]; } else { // with joystick interface, all axes are signed 16 bit with full range axis_min[cnt]=-32768; axis_max[cnt]=32768; } if (axis_min[cnt]>=axis_max[cnt]) { dbgprintf(stderr,"ERROR: bad axis %d value range (%d,%d) [%s:%d]\n", cnt,axis_min[cnt],axis_max[cnt],__FILE__,__LINE__); return(1); } dbgprintf(stderr,"Axis %d : parameters = [%d,%d]\n", cnt,axis_min[cnt],axis_max[cnt]); } //-------------------------------------------------- // force feedback, TBD feature //-------------------------------------------------- #if 0 /* Now get some information about force feedback */ memset(ff_bits,0,32*sizeof(unsigned long)); if (ioctl(device_handle,EVIOCGBIT(EV_FF ,32*sizeof(unsigned long)),ff_bits)<0) { dbgprintf(stderr,"ERROR: can not get ff bits (%s) [%s:%d]\n", strerror(errno),__FILE__,__LINE__); return(1); } /* force feedback supported? */ if (!TEST_BIT(FF_CONSTANT,ff_bits)) { dbgprintf(stderr,"ERROR: device (or driver) has no force feedback support [%s:%d]\n", __FILE__,__LINE__); return(1); } /* Switch off auto centering */ memset(&event,0,sizeof(event)); event.type=EV_FF; event.code=FF_AUTOCENTER; event.value=0; if (write(device_handle,&event,sizeof(event))!=sizeof(event)) { dbgprintf(stderr,"ERROR: failed to disable auto centering (%s) [%s:%d]\n", strerror(errno),__FILE__,__LINE__); return(1); } /* Initialize constant force effect */ memset(&effect,0,sizeof(effect)); effect.type=FF_CONSTANT; effect.id=-1; effect.trigger.button=0; effect.trigger.interval=0; effect.replay.length=0xffff; effect.replay.delay=0; effect.u.constant.level=0; effect.direction=0xC000; effect.u.constant.envelope.attack_length=0; effect.u.constant.envelope.attack_level=0; effect.u.constant.envelope.fade_length=0; effect.u.constant.envelope.fade_level=0; /* Upload effect */ if (ioctl(device_handle,EVIOCSFF,&effect)==-1) { dbgprintf(stderr,"ERROR: uploading effect failed (%s) [%s:%d]\n", strerror(errno),__FILE__,__LINE__); return(1); } /* Start effect */ memset(&event,0,sizeof(event)); event.type=EV_FF; event.code=effect.id; event.value=1; if (write(device_handle,&event,sizeof(event))!=sizeof(event)) { dbgprintf(stderr,"ERROR: starting effect failed (%s) [%s:%d]\n", strerror(errno),__FILE__,__LINE__); return(1); } #endif if (event_mode == STICK_MODE_EVENT ) { ioctl(stick_device_handle, EVIOCGNAME(sizeof(name)), name); } else { ioctl(stick_device_handle, JSIOCGNAME(MAX_NAME_LENGTH), name); } printf("Input device name: \"%s\" on device \"%s\"\n", name, device_name); 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; }
EvdevDevice::EvdevDevice(const std::string& filename) : device(filename) { fd = open(device.c_str(), O_RDONLY | O_NONBLOCK); if (fd == -1) { throw std::runtime_error(filename + ": " + std::string(strerror(errno))); } if (ioctl(fd, EVIOCGVERSION, &version)) { throw std::runtime_error("Error: EvdevDevice: Couldn't get version for " + filename); } if (1) { // FIXME: Some versions of linux don't have these structs, use arrays there struct input_id id; ioctl(fd, EVIOCGID, &id); printf("Input device ID: bus 0x%x vendor 0x%x product 0x%x version 0x%x\n", id.bustype, id.vendor, id.product, id.vendor); } { // Get the human readable name char c_name[256] = "unknown"; ioctl(fd, EVIOCGNAME(sizeof(c_name)), c_name); name = c_name; std::cout << "Name: " << name << std::endl; } { // Read in how many buttons the device has unsigned long bit[EV_MAX][NBITS(KEY_MAX)]; memset(bit, 0, sizeof(bit)); ioctl(fd, EVIOCGBIT(0, EV_MAX), bit[0]); for (int i = 0; i < EV_MAX; i++) { if (test_bit(i, bit[0])) { //printf(" Event type %d (%s)\n", i, events[i] ? events[i] : "?"); if (!i) continue; ioctl(fd, EVIOCGBIT(i, KEY_MAX), bit[i]); for (int j = 0; j < KEY_MAX; j++) { if (test_bit(j, bit[i])) { if (i == EV_KEY) { keys.push_back(Key(j)); } else if (i == EV_ABS) { // FIXME: Some Linuxes don't have these struct struct input_absinfo absinfo; ioctl(fd, EVIOCGABS(j), &absinfo); // FIXME: we are ignoring absinfo.fuzz and // absinfo.flat = deadzone // absinfo.fuzz = values in which range can be considered the same (jitter) absolutes.push_back(Absolute(j, absinfo.minimum, absinfo.maximum, absinfo.value)); } else if (i == EV_REL) { relatives.push_back(Relative(j)); } } } } } } }
void swipe_handle_input(int fd, struct input_event *ev) { int abs_store[6] = {0}; int k; ioctl(fd, EVIOCGABS(ABS_MT_POSITION_X), abs_store); int max_x_touch = abs_store[2]; ioctl(fd, EVIOCGABS(ABS_MT_POSITION_Y), abs_store); int max_y_touch = abs_store[2]; if(ev->type == EV_ABS && ev->code == ABS_MT_TRACKING_ID) { if(in_touch == 0) { in_touch = 1; reset_gestures(); } else { // finger lifted ev->type = EV_KEY; int keywidth = gr_fb_width() / 4; if(slide_right == 1) { ev->code = KEY_POWER; slide_right = 0; } else if(slide_left == 1) { ev->code = KEY_BACK; slide_left = 0; } ev->value = 1; in_touch = 0; reset_gestures(); } } else if(ev->type == EV_ABS && ev->code == ABS_MT_POSITION_X) { old_x = touch_x; float touch_x_rel = (float)ev->value / (float)max_x_touch; touch_x = touch_x_rel * gr_fb_width(); if(old_x != 0) diff_x += touch_x - old_x; if(diff_x > 100) { slide_right = 1; reset_gestures(); } else if(diff_x < -100) { slide_left = 1; reset_gestures(); } } else if(ev->type == EV_ABS && ev->code == ABS_MT_POSITION_Y) { old_y = touch_y; float touch_y_rel = (float)ev->value / (float)max_y_touch; touch_y = touch_y_rel * gr_fb_height(); if(old_y != 0) diff_y += touch_y - old_y; if(diff_y > 80) { ev->code = KEY_VOLUMEDOWN; ev->type = EV_KEY; reset_gestures(); } else if(diff_y < -80) { ev->code = KEY_VOLUMEUP; ev->type = EV_KEY; reset_gestures(); } } return; }
static bool enumerateAxesEvdev(int fd, axes_t *axes) { //printf("Enumerating evdev axes\n"); uint8_t bit[KEY_MAX / 8 + 1]; memset(bit, 0, sizeof(bit)); if(ioctl(fd, EVIOCGBIT(0, EV_MAX), bit) < 0){ ltr_int_my_perror("EVIOCGBIT_1"); return false; } int type; if(!(bit[0] & (1 << EV_ABS))){ //printf("No absolute events available.\n"); return false; } //printf("We have absolute events available!\n"); //We have some absolute axes memset(bit, 0, sizeof(bit)); if(ioctl(fd, EVIOCGBIT(EV_ABS, KEY_MAX), bit) < 0){ ltr_int_my_perror("EVIOCGBIT_2"); return false; } //Get axes number axes->axes = 0; for(type = 0; type < KEY_MAX; ++type){ if(bit[type >> 3] & (1 << (type & 7))){ ++axes->axes; } } if((axes->axesList = (uint8_t*)malloc(axes->axes * sizeof(uint8_t))) == NULL){ ltr_int_my_perror("malloc"); return false; } memset(axes->axesList, 0, axes->axes); if((axes->axisNames = (const char**)malloc(axes->axes * sizeof(char*))) == NULL){ ltr_int_my_perror("malloc"); return false; } if((axes->min = (int*)malloc(axes->axes * sizeof(int))) == NULL){ ltr_int_my_perror("malloc"); return false; } if((axes->max = (int*)malloc(axes->axes * sizeof(int))) == NULL){ ltr_int_my_perror("malloc"); return false; } size_t current = 0; for(type = 0; type < KEY_MAX; ++type){ if(bit[type >> 3] & (1 << (type & 7))){ axes->axesList[current] = type; axes->axisNames[current] = getAxisName(type); struct input_absinfo ai = {0}; if(ioctl(fd, EVIOCGABS(type), &ai) < 0){ ltr_int_my_perror("EVIOCGABS"); free(axes->axesList); free(axes->min); free(axes->max); axes->axesList = NULL; axes->min = NULL; axes->max = NULL; axes->axes = 0; return false; } ltr_int_log_message("Axis: %d (%s)\n", type, getAxisName(type)); ltr_int_log_message(" Val: %d\n", ai.value); ltr_int_log_message(" Minimum: %d\n", ai.minimum); ltr_int_log_message(" Maximum: %d\n", ai.maximum); ltr_int_log_message(" Fuzz: %d\n", ai.fuzz); ltr_int_log_message(" Flat: %d\n", ai.flat); ltr_int_log_message(" Resolution: %d\n", ai.resolution); axes->min[current] = ai.minimum; axes->max[current] = ai.maximum; ++current; } } return true; }
AkmSensor::AkmSensor() : SensorBase(NULL, NULL), mEnabled(0), mPendingMask(0), mInputReader(32) { /* Open the library before opening the input device. The library * creates a uinput device. */ if (loadAKMLibrary() == 0) { data_name = "compass_sensor"; data_fd = openInput("compass_sensor"); } memset(mPendingEvents, 0, sizeof(mPendingEvents)); mPendingEvents[Accelerometer].version = sizeof(sensors_event_t); mPendingEvents[Accelerometer].sensor = ID_A; mPendingEvents[Accelerometer].type = SENSOR_TYPE_ACCELEROMETER; mPendingEvents[Accelerometer].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH; mPendingEvents[MagneticField].version = sizeof(sensors_event_t); mPendingEvents[MagneticField].sensor = ID_M; mPendingEvents[MagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD; mPendingEvents[MagneticField].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH; mPendingEvents[Orientation ].version = sizeof(sensors_event_t); mPendingEvents[Orientation ].sensor = ID_O; mPendingEvents[Orientation ].type = SENSOR_TYPE_ORIENTATION; mPendingEvents[Orientation ].orientation.status = SENSOR_STATUS_ACCURACY_HIGH; // read the actual value of all sensors if they're enabled already struct input_absinfo absinfo; short flags = 0; if (akm_is_sensor_enabled(SENSOR_TYPE_ACCELEROMETER)) { mEnabled |= 1<<Accelerometer; if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo)) { mPendingEvents[Accelerometer].acceleration.x = absinfo.value * CONVERT_A_X; } if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo)) { mPendingEvents[Accelerometer].acceleration.y = absinfo.value * CONVERT_A_Y; } if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo)) { mPendingEvents[Accelerometer].acceleration.z = absinfo.value * CONVERT_A_Z; } } if (akm_is_sensor_enabled(SENSOR_TYPE_MAGNETIC_FIELD)) { mEnabled |= 1<<MagneticField; if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_X), &absinfo)) { mPendingEvents[MagneticField].magnetic.x = absinfo.value * CONVERT_M_X; } if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Y), &absinfo)) { mPendingEvents[MagneticField].magnetic.y = absinfo.value * CONVERT_M_Y; } if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Z), &absinfo)) { mPendingEvents[MagneticField].magnetic.z = absinfo.value * CONVERT_M_Z; } } if (akm_is_sensor_enabled(SENSOR_TYPE_ORIENTATION)) { mEnabled |= 1<<Orientation; if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_YAW), &absinfo)) { mPendingEvents[Orientation].orientation.azimuth = absinfo.value; } if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PITCH), &absinfo)) { mPendingEvents[Orientation].orientation.pitch = absinfo.value; } if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ROLL), &absinfo)) { mPendingEvents[Orientation].orientation.roll = -absinfo.value; } if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ORIENT_STATUS), &absinfo)) { mPendingEvents[Orientation].orientation.status = uint8_t(absinfo.value & SENSOR_STATE_MASK); } } // disable temperature sensor, since it is not supported akm_disable_sensor(SENSOR_TYPE_TEMPERATURE); }
// Get the event types and event codes that the input device supports static PyObject * ioctl_capabilities(PyObject *self, PyObject *args) { int fd, ev_type, ev_code; char ev_bits[EV_MAX/8 + 1], code_bits[KEY_MAX/8 + 1]; struct input_absinfo absinfo; int ret = PyArg_ParseTuple(args, "i", &fd); if (!ret) return NULL; // @todo: figure out why fd gets zeroed on an ioctl after the // refactoring and get rid of this workaround const int _fd = fd; // Capabilities is a mapping of supported event types to lists of handled // events e.g: {1: [272, 273, 274, 275], 2: [0, 1, 6, 8]} PyObject* capabilities = PyDict_New(); PyObject* eventcodes = NULL; PyObject* evlong = NULL; PyObject* capability = NULL; PyObject* py_absinfo = NULL; PyObject* absitem = NULL; memset(&ev_bits, 0, sizeof(ev_bits)); if (ioctl(_fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) < 0) goto on_err; // Build a dictionary of the device's capabilities for (ev_type=0 ; ev_type<EV_MAX ; ev_type++) { if (test_bit(ev_bits, ev_type)) { capability = PyLong_FromLong(ev_type); eventcodes = PyList_New(0); memset(&code_bits, 0, sizeof(code_bits)); ioctl(_fd, EVIOCGBIT(ev_type, sizeof(code_bits)), code_bits); for (ev_code = 0; ev_code < KEY_MAX; ev_code++) { if (test_bit(code_bits, ev_code)) { // Get abs{min,max,fuzz,flat} values for ABS_* event codes if (ev_type == EV_ABS) { memset(&absinfo, 0, sizeof(absinfo)); ioctl(_fd, EVIOCGABS(ev_code), &absinfo); py_absinfo = Py_BuildValue("(iiiiii)", absinfo.value, absinfo.minimum, absinfo.maximum, absinfo.fuzz, absinfo.flat, absinfo.resolution); evlong = PyLong_FromLong(ev_code); absitem = Py_BuildValue("(OO)", evlong, py_absinfo); // absitem -> tuple(ABS_X, (0, 255, 0, 0)) PyList_Append(eventcodes, absitem); Py_DECREF(absitem); Py_DECREF(py_absinfo); } else { evlong = PyLong_FromLong(ev_code); PyList_Append(eventcodes, evlong); } Py_DECREF(evlong); } } // capabilities[EV_KEY] = [KEY_A, KEY_B, KEY_C, ...] // capabilities[EV_ABS] = [(ABS_X, (0, 255, 0, 0)), ...] PyDict_SetItem(capabilities, capability, eventcodes); Py_DECREF(capability); Py_DECREF(eventcodes); } } return capabilities; on_err: PyErr_SetFromErrno(PyExc_IOError); return NULL; }
static void SDL_EVDEV_sync_device(SDL_evdevlist_item *item) { #ifdef EVIOCGMTSLOTS int i, ret; struct input_absinfo abs_info; /* * struct input_mt_request_layout { * __u32 code; * __s32 values[num_slots]; * }; * * this is the structure we're trying to emulate */ __u32* mt_req_code; __s32* mt_req_values; size_t mt_req_size; /* TODO: sync devices other than touchscreen */ if (!item->is_touchscreen) return; mt_req_size = sizeof(*mt_req_code) + sizeof(*mt_req_values) * item->touchscreen_data->max_slots; mt_req_code = SDL_calloc(1, mt_req_size); if (mt_req_code == NULL) { return; } mt_req_values = (__s32*)mt_req_code + 1; *mt_req_code = ABS_MT_TRACKING_ID; ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code); if (ret < 0) { SDL_free(mt_req_code); return; } for(i = 0; i < item->touchscreen_data->max_slots; i++) { /* * This doesn't account for the very edge case of the user removing their * finger and replacing it on the screen during the time we're out of sync, * which'll mean that we're not going from down -> up or up -> down, we're * going from down -> down but with a different tracking id, meaning we'd * have to tell SDL of the two events, but since we wait till SYN_REPORT in * SDL_EVDEV_Poll to tell SDL, the current structure of this code doesn't * allow it. Lets just pray to God it doesn't happen. */ if (item->touchscreen_data->slots[i].tracking_id < 0 && mt_req_values[i] >= 0) { item->touchscreen_data->slots[i].tracking_id = mt_req_values[i]; item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_DOWN; } else if (item->touchscreen_data->slots[i].tracking_id >= 0 && mt_req_values[i] < 0) { item->touchscreen_data->slots[i].tracking_id = -1; item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_UP; } } *mt_req_code = ABS_MT_POSITION_X; ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code); if (ret < 0) { SDL_free(mt_req_code); return; } for(i = 0; i < item->touchscreen_data->max_slots; i++) { if (item->touchscreen_data->slots[i].tracking_id >= 0 && item->touchscreen_data->slots[i].x != mt_req_values[i]) { item->touchscreen_data->slots[i].x = mt_req_values[i]; if (item->touchscreen_data->slots[i].delta == EVDEV_TOUCH_SLOTDELTA_NONE) { item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_MOVE; } } } *mt_req_code = ABS_MT_POSITION_Y; ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code); if (ret < 0) { SDL_free(mt_req_code); return; } for(i = 0; i < item->touchscreen_data->max_slots; i++) { if (item->touchscreen_data->slots[i].tracking_id >= 0 && item->touchscreen_data->slots[i].y != mt_req_values[i]) { item->touchscreen_data->slots[i].y = mt_req_values[i]; if (item->touchscreen_data->slots[i].delta == EVDEV_TOUCH_SLOTDELTA_NONE) { item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_MOVE; } } } ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info); if (ret < 0) { SDL_free(mt_req_code); return; } item->touchscreen_data->current_slot = abs_info.value; SDL_free(mt_req_code); #endif /* EVIOCGMTSLOTS */ }
static void find_joydevs(void) { int i; if (have_joydevs!=-1) { return; } have_joydevs = 0; for (i=0;i<MAX_JOYDEV;i++) { char buf[MAX_PATH]; struct JoyDev joydev = {0}; int fd; int no_ff_check = 0; int j; snprintf(buf,MAX_PATH,EVDEVPREFIX"%d",i); buf[MAX_PATH-1] = 0; if ((fd=open(buf, O_RDWR))==-1) { fd = open(buf, O_RDONLY); no_ff_check = 1; } if (fd!=-1) { if ((-1==ioctl(fd,EVIOCGBIT(0,sizeof(joydev.evbits)),joydev.evbits))) { perror("EVIOCGBIT 0"); close(fd); continue; } if (-1==ioctl(fd,EVIOCGBIT(EV_ABS,sizeof(joydev.absbits)),joydev.absbits)) { perror("EVIOCGBIT EV_ABS"); close(fd); continue; } if (-1==ioctl(fd,EVIOCGBIT(EV_KEY,sizeof(joydev.keybits)),joydev.keybits)) { perror("EVIOCGBIT EV_KEY"); close(fd); continue; } /* A true joystick has at least axis X and Y, and at least 1 * button. copied from linux/drivers/input/joydev.c */ if (test_bit(joydev.absbits,ABS_X) && test_bit(joydev.absbits,ABS_Y) && ( test_bit(joydev.keybits,BTN_TRIGGER) || test_bit(joydev.keybits,BTN_A) || test_bit(joydev.keybits,BTN_1) ) ) { joydev.device = strdup(buf); if (-1!=ioctl(fd, EVIOCGNAME(MAX_PATH-1), buf)) { buf[MAX_PATH-1] = 0; joydev.name = strdup(buf); } else { joydev.name = joydev.device; } joydev.guid = DInput_Wine_Joystick_Base_GUID; joydev.guid.Data3 += have_joydevs; TRACE("Found a joystick on %s: %s (%s)\n", joydev.device, joydev.name, debugstr_guid(&joydev.guid) ); #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION if (!no_ff_check && test_bit(joydev.evbits, EV_FF) && ioctl(fd, EVIOCGBIT(EV_FF, sizeof(joydev.ffbits)), joydev.ffbits) != -1 && ioctl(fd, EVIOCGEFFECTS, &joydev.num_effects) != -1 && joydev.num_effects > 0) { TRACE(" ... with force feedback\n"); joydev.has_ff = 1; } #endif for (j=0;j<ABS_MAX;j++) { if (test_bit(joydev.absbits,j)) { if (-1!=ioctl(fd,EVIOCGABS(j),&(joydev.axes[j]))) { TRACE(" ... with axis %d: cur=%d, min=%d, max=%d, fuzz=%d, flat=%d\n", j, joydev.axes[j].value, joydev.axes[j].minimum, joydev.axes[j].maximum, joydev.axes[j].fuzz, joydev.axes[j].flat ); } } } if (have_joydevs==0) { joydevs = HeapAlloc(GetProcessHeap(), 0, sizeof(struct JoyDev)); } else { HeapReAlloc(GetProcessHeap(), 0, joydevs, (1+have_joydevs) * sizeof(struct JoyDev)); } memcpy(joydevs+have_joydevs, &joydev, sizeof(struct JoyDev)); have_joydevs++; } close(fd); } } }
AkmSensor::AkmSensor() : SensorBase(AKM_DEVICE_NAME, "compass"), mEnabled(0), mPendingMask(0), mInputReader(32) { memset(mPendingEvents, 0, sizeof(mPendingEvents)); mPendingEvents[Accelerometer].version = sizeof(sensors_event_t); mPendingEvents[Accelerometer].sensor = ID_A; mPendingEvents[Accelerometer].type = SENSOR_TYPE_ACCELEROMETER; mPendingEvents[Accelerometer].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH; mPendingEvents[MagneticField].version = sizeof(sensors_event_t); mPendingEvents[MagneticField].sensor = ID_M; mPendingEvents[MagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD; mPendingEvents[MagneticField].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH; mPendingEvents[Orientation ].version = sizeof(sensors_event_t); mPendingEvents[Orientation ].sensor = ID_O; mPendingEvents[Orientation ].type = SENSOR_TYPE_ORIENTATION; mPendingEvents[Orientation ].orientation.status = SENSOR_STATUS_ACCURACY_HIGH; for (int i=0 ; i<numSensors ; i++) mDelays[i] = 200000000; // 200 ms by default // read the actual value of all sensors if they're enabled already struct input_absinfo absinfo; short flags = 0; open_device(); if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_AFLAG, &flags)) { if (flags) { mEnabled |= 1<<Accelerometer; if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo)) { mPendingEvents[Accelerometer].acceleration.x = absinfo.value * CONVERT_A_X; } if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo)) { mPendingEvents[Accelerometer].acceleration.y = absinfo.value * CONVERT_A_Y; } if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo)) { mPendingEvents[Accelerometer].acceleration.z = absinfo.value * CONVERT_A_Z; } } } if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_MVFLAG, &flags)) { if (flags) { mEnabled |= 1<<MagneticField; if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_X), &absinfo)) { mPendingEvents[MagneticField].magnetic.x = absinfo.value * CONVERT_M_X; } if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Y), &absinfo)) { mPendingEvents[MagneticField].magnetic.y = absinfo.value * CONVERT_M_Y; } if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Z), &absinfo)) { mPendingEvents[MagneticField].magnetic.z = absinfo.value * CONVERT_M_Z; } } } if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_MFLAG, &flags)) { if (flags) { mEnabled |= 1<<Orientation; if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_YAW), &absinfo)) { mPendingEvents[Orientation].orientation.azimuth = absinfo.value; } if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PITCH), &absinfo)) { mPendingEvents[Orientation].orientation.pitch = absinfo.value; } if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ROLL), &absinfo)) { mPendingEvents[Orientation].orientation.roll = -absinfo.value; } if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ORIENT_STATUS), &absinfo)) { mPendingEvents[Orientation].orientation.status = uint8_t(absinfo.value & SENSOR_STATE_MASK); } } } // disable temperature sensor, since it is not reported flags = 0; ioctl(dev_fd, ECS_IOCTL_APP_SET_TFLAG, &flags); if (!mEnabled) { close_device(); } }
static void ConfigJoystick(SDL_Joystick * joystick, int fd) { int i, t; unsigned long keybit[NBITS(KEY_MAX)] = { 0 }; unsigned long absbit[NBITS(ABS_MAX)] = { 0 }; unsigned long relbit[NBITS(REL_MAX)] = { 0 }; /* See if this device uses the new unified event API */ if ((ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) && (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) && (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0)) { /* Get the number of buttons, axes, and other thingamajigs */ for (i = BTN_JOYSTICK; i < KEY_MAX; ++i) { if (test_bit(i, keybit)) { #ifdef DEBUG_INPUT_EVENTS printf("Joystick has button: 0x%x\n", i); #endif joystick->hwdata->key_map[i] = joystick->nbuttons; ++joystick->nbuttons; } } for (i = 0; i < BTN_JOYSTICK; ++i) { if (test_bit(i, keybit)) { #ifdef DEBUG_INPUT_EVENTS printf("Joystick has button: 0x%x\n", i); #endif joystick->hwdata->key_map[i] = joystick->nbuttons; ++joystick->nbuttons; } } for (i = 0; i < ABS_MAX; ++i) { /* Skip hats */ if (i == ABS_HAT0X) { i = ABS_HAT3Y; continue; } if (test_bit(i, absbit)) { struct input_absinfo absinfo; if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) { continue; } #ifdef DEBUG_INPUT_EVENTS printf("Joystick has absolute axis: 0x%.2x\n", i); printf("Values = { %d, %d, %d, %d, %d }\n", absinfo.value, absinfo.minimum, absinfo.maximum, absinfo.fuzz, absinfo.flat); #endif /* DEBUG_INPUT_EVENTS */ joystick->hwdata->abs_map[i] = joystick->naxes; if (absinfo.minimum == absinfo.maximum) { joystick->hwdata->abs_correct[i].used = 0; } else { joystick->hwdata->abs_correct[i].used = 1; joystick->hwdata->abs_correct[i].coef[0] = (absinfo.maximum + absinfo.minimum) - 2 * absinfo.flat; joystick->hwdata->abs_correct[i].coef[1] = (absinfo.maximum + absinfo.minimum) + 2 * absinfo.flat; t = ((absinfo.maximum - absinfo.minimum) - 4 * absinfo.flat); if (t != 0) { joystick->hwdata->abs_correct[i].coef[2] = (1 << 28) / t; } else { joystick->hwdata->abs_correct[i].coef[2] = 0; } } ++joystick->naxes; } } for (i = ABS_HAT0X; i <= ABS_HAT3Y; i += 2) { if (test_bit(i, absbit) || test_bit(i + 1, absbit)) { struct input_absinfo absinfo; if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) { continue; } #ifdef DEBUG_INPUT_EVENTS printf("Joystick has hat %d\n", (i - ABS_HAT0X) / 2); printf("Values = { %d, %d, %d, %d, %d }\n", absinfo.value, absinfo.minimum, absinfo.maximum, absinfo.fuzz, absinfo.flat); #endif /* DEBUG_INPUT_EVENTS */ ++joystick->nhats; } } if (test_bit(REL_X, relbit) || test_bit(REL_Y, relbit)) { ++joystick->nballs; } /* Allocate data to keep track of these thingamajigs */ if (joystick->nhats > 0) { if (allocate_hatdata(joystick) < 0) { joystick->nhats = 0; } } if (joystick->nballs > 0) { if (allocate_balldata(joystick) < 0) { joystick->nballs = 0; } } } }
static int vk_init(struct ev *e) { char vk_path[PATH_MAX] = "/sys/board_properties/virtualkeys."; char vks[2048], *ts = NULL; ssize_t len; int vk_fd; int i; e->vk_count = 0; len = strlen(vk_path); len = ioctl(e->fd->fd, EVIOCGNAME(sizeof(e->deviceName)), e->deviceName); if (len <= 0) { printf("Unable to query event object.\n"); return -1; } #ifdef _EVENT_LOGGING printf("Event object: %s\n", e->deviceName); #endif // Blacklist these "input" devices if (strcmp(e->deviceName, "bma250") == 0 || strcmp(e->deviceName, "bma150") == 0 || strcmp(e->deviceName, "accelerometer") == 0) { e->ignored = 1; } strcat(vk_path, e->deviceName); // Some devices split the keys from the touchscreen e->vk_count = 0; vk_fd = open(vk_path, O_RDONLY); if (vk_fd >= 0) { len = read(vk_fd, vks, sizeof(vks)-1); close(vk_fd); if (len <= 0) return -1; vks[len] = '\0'; /* Parse a line like: keytype:keycode:centerx:centery:width:height:keytype2:keycode2:centerx2:... */ for (ts = vks, e->vk_count = 1; *ts; ++ts) { if (*ts == ':') ++e->vk_count; } if (e->vk_count % 6) { printf("minui: %s is %d %% 6\n", vk_path, e->vk_count % 6); } e->vk_count /= 6; if (e->vk_count <= 0) return -1; e->down = DOWN_NOT; } ioctl(e->fd->fd, EVIOCGABS(ABS_X), &e->p.xi); ioctl(e->fd->fd, EVIOCGABS(ABS_Y), &e->p.yi); e->p.synced = 0; #ifdef _EVENT_LOGGING printf("EV: ST minX: %d maxX: %d minY: %d maxY: %d\n", e->p.xi.minimum, e->p.xi.maximum, e->p.yi.minimum, e->p.yi.maximum); #endif ioctl(e->fd->fd, EVIOCGABS(ABS_MT_POSITION_X), &e->mt_p.xi); ioctl(e->fd->fd, EVIOCGABS(ABS_MT_POSITION_Y), &e->mt_p.yi); e->mt_p.synced = 0; #ifdef _EVENT_LOGGING printf("EV: MT minX: %d maxX: %d minY: %d maxY: %d\n", e->mt_p.xi.minimum, e->mt_p.xi.maximum, e->mt_p.yi.minimum, e->mt_p.yi.maximum); #endif e->vks = malloc(sizeof(*e->vks) * e->vk_count); for (i = 0; i < e->vk_count; ++i) { char *token[6]; int j; for (j = 0; j < 6; ++j) { token[j] = vk_strtok_r((i||j)?NULL:vks, ":", &ts); } if (strcmp(token[0], "0x01") != 0) { /* Java does string compare, so we do too. */ printf("minui: %s: ignoring unknown virtual key type %s\n", vk_path, token[0]); continue; } e->vks[i].scancode = strtol(token[1], NULL, 0); e->vks[i].centerx = strtol(token[2], NULL, 0); e->vks[i].centery = strtol(token[3], NULL, 0); e->vks[i].width = strtol(token[4], NULL, 0); e->vks[i].height = strtol(token[5], NULL, 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; }
int evio_get_spaceball_status(evio_handle v, int *rel_x, int *rel_y, int *rel_z, int *rel_rx, int *rel_ry, int *rel_rz, int *buttons) { struct input_absinfo absinfo; evio *evp = (evio *) v; int rc=0; *rel_x = 0; *rel_y = 0; *rel_z = 0; *rel_rx = 0; *rel_ry = 0; *rel_rz = 0; *buttons = 0; memset(&absinfo, 0, sizeof(absinfo)); if (ioctl(evp->fd, EVIOCGABS(REL_X), &absinfo) < 0) { return 0; } else { rc |= 1; *rel_x = absinfo.value; } if (ioctl(evp->fd, EVIOCGABS(REL_Y), &absinfo) < 0) { return 0; } else { rc |= 1; *rel_y = absinfo.value; } if (ioctl(evp->fd, EVIOCGABS(REL_Z), &absinfo) < 0) { return 0; } else { rc |= 1; *rel_z = absinfo.value; } if (ioctl(evp->fd, EVIOCGABS(REL_RX), &absinfo) < 0) { return 0; } else { rc |= 1; *rel_rx = absinfo.value; } if (ioctl(evp->fd, EVIOCGABS(REL_RY), &absinfo) < 0) { return 0; } else { rc |= 1; *rel_ry = absinfo.value; } if (ioctl(evp->fd, EVIOCGABS(REL_RZ), &absinfo) < 0) { return 0; } else { rc |= 1; *rel_rz = absinfo.value; } if (ioctl(evp->fd, EVIOCGBIT(EV_KEY, sizeof(evp->keybit)), evp->keybit) >= 0) { int i, btmp=0; for (i=0; i<31; i++) { if (EVIO_TESTBIT(BTN_MISC+i, evp->keybit)) btmp |= (1 << i); } *buttons = btmp; } return rc; }
int open_dev_usb(struct device *dev) { int i; struct input_absinfo absinfo; unsigned char evtype_mask[(EV_MAX + 7) / 8]; if((dev->fd = open(dev->path, O_RDWR)) == -1) { if((dev->fd = open(dev->path, O_RDONLY)) == -1) { perror("failed to open device"); return -1; } fprintf(stderr, "opened device read-only, LEDs won't work\n"); } if(ioctl(dev->fd, EVIOCGNAME(sizeof dev->name), dev->name) == -1) { perror("EVIOCGNAME ioctl failed"); strcpy(dev->name, "unknown"); } printf("device name: %s\n", dev->name); /* get number of axes */ dev->num_axes = 6; /* default to regular 6dof controller axis count */ if(ioctl(dev->fd, EVIOCGBIT(EV_ABS, sizeof evtype_mask), evtype_mask) == 0) { dev->num_axes = 0; for(i=0; i<ABS_CNT; i++) { int idx = i / 8; int bit = i % 8; if(evtype_mask[idx] & (1 << bit)) { dev->num_axes++; } else { break; } } } if(verbose) { printf(" Number of axes: %d\n", dev->num_axes); } dev->minval = malloc(dev->num_axes * sizeof *dev->minval); dev->maxval = malloc(dev->num_axes * sizeof *dev->maxval); dev->fuzz = malloc(dev->num_axes * sizeof *dev->fuzz); if(!dev->minval || !dev->maxval || !dev->fuzz) { perror("failed to allocate memory"); return -1; } /* if the device is an absolute device, find the minimum and maximum axis values */ for(i=0; i<dev->num_axes; i++) { dev->minval[i] = DEF_MINVAL; dev->maxval[i] = DEF_MAXVAL; dev->fuzz[i] = 0; if(ioctl(dev->fd, EVIOCGABS(i), &absinfo) == 0) { dev->minval[i] = absinfo.minimum; dev->maxval[i] = absinfo.maximum; dev->fuzz[i] = absinfo.fuzz; if(verbose) { printf(" Axis %d value range: %d - %d (fuzz: %d)\n", i, dev->minval[i], dev->maxval[i], dev->fuzz[i]); } } } /*if(ioctl(dev->fd, EVIOCGBIT(0, sizeof(evtype_mask)), evtype_mask) == -1) { perror("EVIOCGBIT ioctl failed\n"); close(dev->fd); return -1; }*/ if(cfg.grab_device) { int grab = 1; /* try to grab the device */ if(ioctl(dev->fd, EVIOCGRAB, &grab) == -1) { perror("failed to grab the device"); } } /* set non-blocking */ fcntl(dev->fd, F_SETFL, fcntl(dev->fd, F_GETFL) | O_NONBLOCK); if(cfg.led) { set_led_evdev(dev, 1); } /* fill the device function pointers */ dev->close = close_evdev; dev->read = read_evdev; dev->set_led = set_led_evdev; return 0; }