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
This commit is contained in:
fireclawthefox 2016-08-03 20:20:01 +02:00
parent a98cc38c90
commit 670efb9e64
2 changed files with 108 additions and 32 deletions

View File

@ -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.

View File

@ -77,6 +77,9 @@ PUBLISHED:
// Head-mounted display.
DC_hmd,
// Count of this enum, used for loops
DC_COUNT,
};
protected: