From 670efb9e646b0cd17404b6d14fa754ce5d715f2d Mon Sep 17 00:00:00 2001 From: fireclawthefox Date: Wed, 3 Aug 2016 20:20:01 +0200 Subject: [PATCH] Extended device class heuristics Extended and partly restructured the way how the device class gets set Added DC_COUNT to the DeviceClass enum to simplify loop checks --- panda/src/device/evdevInputDevice.cxx | 137 ++++++++++++++++++++------ panda/src/device/inputDevice.h | 3 + 2 files changed, 108 insertions(+), 32 deletions(-) diff --git a/panda/src/device/evdevInputDevice.cxx b/panda/src/device/evdevInputDevice.cxx index 0bc4a8d9ff..bdc82df218 100644 --- a/panda/src/device/evdevInputDevice.cxx +++ b/panda/src/device/evdevInputDevice.cxx @@ -227,6 +227,7 @@ init_device() { } _name.assign(name); + //cerr << "##### Now initializing device " << name << "\n"; struct input_id id; if (ioctl(_fd, EVIOCGID, &id) >= 0) { @@ -237,12 +238,111 @@ init_device() { bool all_values_zero = true; bool emulate_dpad = true; + bool has_keys = false; + bool has_axes = false; + + uint8_t keys[(KEY_CNT + 7) >> 3]; if (test_bit(EV_KEY, evtypes)) { // Check which buttons are on the device. - uint8_t keys[(KEY_CNT + 7) >> 3]; memset(keys, 0, sizeof(keys)); ioctl(_fd, EVIOCGBIT(EV_KEY, sizeof(keys)), keys); + has_keys = true; + if (test_bit(KEY_A, keys) && test_bit(KEY_Z, keys)) { + _flags |= IDF_has_keyboard; + } + } + + int num_bits = 0; + uint8_t axes[(ABS_CNT + 7) >> 3]; + if (test_bit(EV_ABS, evtypes)) { + // Check which axes are on the device. + memset(axes, 0, sizeof(axes)); + num_bits = ioctl(_fd, EVIOCGBIT(EV_ABS, sizeof(axes)), axes) << 3; + has_axes = true; + } + + + // Try to detect which type of device we have here + int device_scores[DC_COUNT]; + memset(device_scores, 0, sizeof(device_scores)); + + // Test for specific keys + if (test_bit(BTN_GAMEPAD, keys)) { + device_scores[DC_gamepad] += 5; + device_scores[DC_steering_wheel] += 5; + device_scores[DC_flight_stick] += 5; + } + + if (test_bit(ABS_WHEEL, axes) && test_bit(ABS_GAS, axes) && test_bit(ABS_BRAKE, axes)) { + device_scores[DC_steering_wheel] += 10; + } + if (test_bit(BTN_GEAR_DOWN, keys) && test_bit(BTN_GEAR_UP, keys)) { + device_scores[DC_steering_wheel] += 10; + } + if (test_bit(BTN_JOYSTICK, keys)) { + device_scores[DC_flight_stick] += 10; + } + if (test_bit(BTN_MOUSE, keys)) { + device_scores[DC_mouse] += 20; + } + uint8_t unknown_keys[] = {KEY_POWER}; + for (int i = 0; i < 1; i++) { + if (test_bit(unknown_keys[i], keys)) { + if (unknown_keys[i] == KEY_POWER) { + } + device_scores[DC_unknown] += 20; + } + } + if (_flags & IDF_has_keyboard) { + device_scores[DC_keyboard] += 20; + } + + // Test for specific name tags + string lowercase_name = _name; + for(int x=0; x<_name.length(); x++) { + lowercase_name[x]=tolower(lowercase_name[x]); + } + if (lowercase_name.find("gamepad") != string::npos) { + device_scores[DC_gamepad] += 10; + } + if (lowercase_name.find("wheel") != string::npos) { + device_scores[DC_steering_wheel] += 10; + } + if (lowercase_name.find("mouse") != string::npos || lowercase_name.find("touchpad") != string::npos) { + device_scores[DC_mouse] += 10; + } + if (lowercase_name.find("keyboard") != string::npos) { + device_scores[DC_keyboard] += 10; + } + // List of lowercase names that occur in unknown devices + string unknown_names[] = {"video bus", "power button", "sleep button"}; + for(int i = 0; i < 3; i++) { + if (lowercase_name.find(unknown_names[i]) != string::npos) { + device_scores[DC_unknown] += 20; + } + } + + // Check which device type got the most points + bool highscore_found = false; + size_t highest_score = 0; + while (!highscore_found) { + highscore_found = true; + for (size_t i = 0; i < DC_COUNT; i++) { + if (device_scores[i] > highest_score) { + highest_score = device_scores[i]; + _device_class = (DeviceClass)i; + highscore_found = false; + } + } + } + //cerr << "Found highscore class " << _device_class << " with this score: " << highest_score << "\n"; + + if (_device_class != DC_gamepad) { + emulate_dpad = false; + } + + if (has_keys) { // Also check whether the buttons are currently pressed. uint8_t states[(KEY_CNT + 7) >> 3]; memset(states, 0, sizeof(states)); @@ -252,6 +352,7 @@ init_device() { for (int i = 0; i < KEY_CNT; ++i) { if (test_bit(i, keys)) { set_button_map(bi, map_button(i)); + //cerr << "Button " << bi << " is mapped by the driver to " << i << "\n"; if (test_bit(i, states)) { _buttons[bi]._state = S_down; all_values_zero = false; @@ -264,44 +365,15 @@ init_device() { ++bi; } } - - if (test_bit(KEY_A, keys) && test_bit(KEY_Z, keys)) { - _flags |= IDF_has_keyboard; - } - - // Check device type. - if (test_bit(BTN_GAMEPAD, keys)) { - _device_class = DC_gamepad; - - } else if (test_bit(BTN_JOYSTICK, keys)) { - _device_class = DC_flight_stick; - - } else if (test_bit(BTN_MOUSE, keys)) { - _device_class = DC_mouse; - - } else if (test_bit(BTN_WHEEL, keys)) { - _device_class = DC_steering_wheel; - - } else if (_flags & IDF_has_keyboard) { - _device_class = DC_keyboard; - } } - if (_device_class != DC_gamepad) { - emulate_dpad = false; - } - - if (test_bit(EV_ABS, evtypes)) { - // Check which axes are on the device. - uint8_t axes[(ABS_CNT + 7) >> 3]; - memset(axes, 0, sizeof(axes)); - + if (has_axes) { AxisRange range; range._scale = 1.0; range._bias = 0.0; _axis_ranges.resize(ABS_CNT, range); - int num_bits = ioctl(_fd, EVIOCGBIT(EV_ABS, sizeof(axes)), axes) << 3; + for (int i = 0; i < num_bits; ++i) { if (test_bit(i, axes)) { if (i >= ABS_HAT0X) { @@ -322,6 +394,7 @@ init_device() { } } else { set_control_map(i, axis_map[i]); + //cerr << "Axis " << axis_map[i] << " is mapped by the driver to " << i << "\n"; } // Check the initial value and ranges. diff --git a/panda/src/device/inputDevice.h b/panda/src/device/inputDevice.h index e2e62735ff..3d90bc60dd 100644 --- a/panda/src/device/inputDevice.h +++ b/panda/src/device/inputDevice.h @@ -77,6 +77,9 @@ PUBLISHED: // Head-mounted display. DC_hmd, + + // Count of this enum, used for loops + DC_COUNT, }; protected: